Hibernate SVN: r10823 - branches/Branch_3_2/HibernateExt/tools
by hibernate-commits@lists.jboss.org
Author: max.andersen(a)jboss.com
Date: 2006-11-16 12:33:12 -0500 (Thu, 16 Nov 2006)
New Revision: 10823
Modified:
branches/Branch_3_2/HibernateExt/tools/build.xml
Log:
bump
Modified: branches/Branch_3_2/HibernateExt/tools/build.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/tools/build.xml 2006-11-16 17:32:12 UTC (rev 10822)
+++ branches/Branch_3_2/HibernateExt/tools/build.xml 2006-11-16 17:33:12 UTC (rev 10823)
@@ -7,7 +7,7 @@
<!-- Name of project and version, used to create filenames -->
<property name="Name" value="Hibernate Tools"/>
<property name="name" value="hibernate-tools"/>
- <property name="version" value="3.2.0beta8"/>
+ <property name="version" value="3.2.0snapshotb9"/>
<property name="javadoc.packagenames" value="org.hibernate.tool"/>
17 years, 5 months
Hibernate SVN: r10822 - in branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool: . hbm2x hbm2x/doc
by hibernate-commits@lists.jboss.org
Author: max.andersen(a)jboss.com
Date: 2006-11-16 12:32:12 -0500 (Thu, 16 Nov 2006)
New Revision: 10822
Modified:
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/Version.java
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/DocExporter.java
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/TemplateHelper.java
branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/doc/DocFileManager.java
Log:
don't use copy for text files to avoid user overriding the templates by having an old hibernate-tools.jar in their eclipse classpath
Modified: branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/Version.java
===================================================================
--- branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/Version.java 2006-11-16 16:56:49 UTC (rev 10821)
+++ branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/Version.java 2006-11-16 17:32:12 UTC (rev 10822)
@@ -5,7 +5,7 @@
final public class Version {
- public static final String VERSION = "3.2.0.beta8";
+ public static final String VERSION = "3.2.0.snapshotb9";
private static final Version instance = new Version();
Modified: branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/DocExporter.java
===================================================================
--- branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/DocExporter.java 2006-11-16 16:56:49 UTC (rev 10821)
+++ branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/DocExporter.java 2006-11-16 17:32:12 UTC (rev 10822)
@@ -5,6 +5,7 @@
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -287,20 +288,20 @@
try {
DocFile cssStylesDocFile = docFileManager.getCssStylesDocFile();
- DocFileManager.copy(FILE_CSS_DEFINITION, cssStylesDocFile.getFile() );
+ processTemplate(Collections.EMPTY_MAP, FILE_CSS_DEFINITION, cssStylesDocFile.getFile());
DocFile hibernateLogoDocFile = docFileManager.getHibernateImageDocFile();
- DocFileManager.copy(FILE_HIBERNATE_IMAGE,
+ DocFileManager.copy(this.getClass().getClassLoader(), FILE_HIBERNATE_IMAGE,
hibernateLogoDocFile.getFile() );
DocFile extendsImageDocFile = docFileManager.getExtendsImageDocFile();
- DocFileManager.copy(FILE_EXTENDS_IMAGE, extendsImageDocFile.getFile());
+ DocFileManager.copy(this.getClass().getClassLoader(), FILE_EXTENDS_IMAGE, extendsImageDocFile.getFile());
DocFile mainIndexDocFile = docFileManager.getMainIndexDocFile();
- DocFileManager.copy(FILE_INDEX, mainIndexDocFile.getFile() );
+ processTemplate(Collections.EMPTY_MAP, FILE_INDEX, mainIndexDocFile.getFile() );
}
catch (IOException ioe) {
throw new RuntimeException("Error while copying files.", ioe);
Modified: branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/TemplateHelper.java
===================================================================
--- branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/TemplateHelper.java 2006-11-16 16:56:49 UTC (rev 10821)
+++ branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/TemplateHelper.java 2006-11-16 17:32:12 UTC (rev 10822)
@@ -7,6 +7,7 @@
import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
@@ -85,6 +86,7 @@
}
+
public class Templates {
/*public String get(String name) {
@@ -287,5 +289,6 @@
catch (IOException e) {
throw new ExporterException("templateExists for " + templateName + " failed", e);
}
- }
+ }
+
}
Modified: branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/doc/DocFileManager.java
===================================================================
--- branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/doc/DocFileManager.java 2006-11-16 16:56:49 UTC (rev 10821)
+++ branches/Branch_3_2/HibernateExt/tools/src/java/org/hibernate/tool/hbm2x/doc/DocFileManager.java 2006-11-16 17:32:12 UTC (rev 10822)
@@ -475,27 +475,30 @@
/**
* Copy a File.
*
- * TODO: this method ignores custom provided templatepath. Want to call velocity to get the resourceloaders but they are hidden, so we need another way.
- *
+ * TODO: this method ignores custom provided templatepath. Want to call freemarker to get the resourceloaders but they are hidden, so we need another way.
+ * ..and if we use currentthread classloader you might conflict with the projects tools.jar
+ *
* @param fileName the name of the file to copy.
* @param to the target file.
*
* @throws IOException in case of error.
*/
- public static void copy(String fileName, File to) throws IOException {
+ public static void copy(ClassLoader loader, String fileName, File to) throws IOException {
InputStream is = null;
FileOutputStream out = null;
try {
- ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ /*ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = DocFileManager.class.getClassLoader();
}
- is = classLoader.getResourceAsStream(fileName);
- if (is == null && classLoader!=DocFileManager.class.getClassLoader() ) {
+ is = classLoader.getResourceAsStream(fileName);*/
+
+ /*if (is == null && classLoader!=DocFileManager.class.getClassLoader() ) {
is = DocFileManager.class.getClassLoader().getResourceAsStream(fileName); // HACK: workaround since eclipse for some reason doesnt provide the right classloader;
- }
+ } */
+ is = loader.getResourceAsStream( fileName );
if(is==null) {
throw new IllegalArgumentException("File not found: "
17 years, 5 months
Hibernate SVN: r10821 - trunk/Hibernate3/src/org/hibernate/hql/ast/util
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-11-16 11:56:49 -0500 (Thu, 16 Nov 2006)
New Revision: 10821
Modified:
trunk/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java
Log:
general cleanup
Modified: trunk/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java 2006-11-16 16:56:35 UTC (rev 10820)
+++ trunk/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java 2006-11-16 16:56:49 UTC (rev 10821)
@@ -29,11 +29,13 @@
import antlr.collections.AST;
/**
- * Wraps SessionFactoryImpl, adding more lookup behaviors and encapsulating some of the error handling.
+ * Helper for performing common and/or complex operations with the
+ * {@link SessionFactoryImplementor} during translation of an HQL query.
*
- * @author josh Jul 24, 2004 6:44:00 PM
+ * @author Joshua Davis
*/
public class SessionFactoryHelper {
+
private SessionFactoryImplementor sfi;
private Map collectionPropertyMappingByRole;
@@ -92,18 +94,18 @@
* @return The defined persister for this class, or null if none found.
*/
public Queryable findQueryableUsingImports(String className) {
- return SessionFactoryHelper.findQueryableUsingImports(sfi,className);
+ return findQueryableUsingImports( sfi, className );
}
/**
- * Given a (potentially unqualified) class name, locate its persister. (static version)
+ * Given a (potentially unqualified) class name, locate its persister.
+ *
* @param sfi The session factory implementor.
* @param className The (potentially unqualified) class name.
* @return The defined persister for this class, or null if none found.
*/
- public static Queryable findQueryableUsingImports(SessionFactoryImplementor sfi,String className)
- {
+ public static Queryable findQueryableUsingImports(SessionFactoryImplementor sfi, String className) {
final String importedClassName = sfi.getImportedClassName( className );
if ( importedClassName == null ) {
return null;
@@ -124,7 +126,7 @@
* @throws MappingException
*/
private EntityPersister findEntityPersisterByName(String name) throws MappingException {
- // First, try to get the persister using the class name directly.
+ // First, try to get the persister using the given name directly.
try {
return sfi.getEntityPersister( name );
}
@@ -153,8 +155,6 @@
try {
cp = findEntityPersisterByName( name );
if ( cp == null ) {
-// throw new SemanticException( name + " is not mapped." );
-// throw new QuerySyntaxException( new SemanticException( name + " is not mapped." ) );
throw new QuerySyntaxException( name + " is not mapped" );
}
}
@@ -365,15 +365,26 @@
* @return the function return type given the function name and the first argument expression node.
*/
public Type findFunctionReturnType(String functionName, AST first) {
+ // locate the registered function by the given name
+ SQLFunction sqlFunction = requireSQLFunction( functionName );
+
+ // determine the type of the first argument...
Type argumentType = null;
- if ( "cast".equals(functionName) ) {
- argumentType = TypeFactory.heuristicType( first.getNextSibling().getText() );
+ if ( first != null ) {
+ if ( "cast".equals(functionName) ) {
+ argumentType = TypeFactory.heuristicType( first.getNextSibling().getText() );
+ }
+ else if ( first instanceof SqlNode ) {
+ argumentType = ( (SqlNode) first ).getDataType();
+ }
}
- else if ( first != null && first instanceof SqlNode ) {
- argumentType = ( (SqlNode) first ).getDataType();
+
+ Type rtnType = sqlFunction.getReturnType( argumentType, sfi );
+ if ( rtnType == null ) {
+ throw new QueryException( "unable to determine function return type [" + functionName + "]" );
}
- // This implementation is a bit strange, but then that's why this helper exists.
- return requireSQLFunction( functionName ).getReturnType( argumentType, sfi );
+
+ return rtnType;
}
public String[][] generateColumnNames(Type[] sqlResultTypes) {
17 years, 5 months
Hibernate SVN: r10820 - branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-11-16 11:56:35 -0500 (Thu, 16 Nov 2006)
New Revision: 10820
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java
Log:
general cleanup
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java 2006-11-16 05:12:20 UTC (rev 10819)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/hql/ast/util/SessionFactoryHelper.java 2006-11-16 16:56:35 UTC (rev 10820)
@@ -29,11 +29,13 @@
import antlr.collections.AST;
/**
- * Wraps SessionFactoryImpl, adding more lookup behaviors and encapsulating some of the error handling.
+ * Helper for performing common and/or complex operations with the
+ * {@link SessionFactoryImplementor} during translation of an HQL query.
*
- * @author josh Jul 24, 2004 6:44:00 PM
+ * @author Joshua Davis
*/
public class SessionFactoryHelper {
+
private SessionFactoryImplementor sfi;
private Map collectionPropertyMappingByRole;
@@ -92,18 +94,18 @@
* @return The defined persister for this class, or null if none found.
*/
public Queryable findQueryableUsingImports(String className) {
- return SessionFactoryHelper.findQueryableUsingImports(sfi,className);
+ return findQueryableUsingImports( sfi, className );
}
/**
- * Given a (potentially unqualified) class name, locate its persister. (static version)
+ * Given a (potentially unqualified) class name, locate its persister.
+ *
* @param sfi The session factory implementor.
* @param className The (potentially unqualified) class name.
* @return The defined persister for this class, or null if none found.
*/
- public static Queryable findQueryableUsingImports(SessionFactoryImplementor sfi,String className)
- {
+ public static Queryable findQueryableUsingImports(SessionFactoryImplementor sfi, String className) {
final String importedClassName = sfi.getImportedClassName( className );
if ( importedClassName == null ) {
return null;
@@ -124,7 +126,7 @@
* @throws MappingException
*/
private EntityPersister findEntityPersisterByName(String name) throws MappingException {
- // First, try to get the persister using the class name directly.
+ // First, try to get the persister using the given name directly.
try {
return sfi.getEntityPersister( name );
}
@@ -153,8 +155,6 @@
try {
cp = findEntityPersisterByName( name );
if ( cp == null ) {
-// throw new SemanticException( name + " is not mapped." );
-// throw new QuerySyntaxException( new SemanticException( name + " is not mapped." ) );
throw new QuerySyntaxException( name + " is not mapped" );
}
}
@@ -365,15 +365,26 @@
* @return the function return type given the function name and the first argument expression node.
*/
public Type findFunctionReturnType(String functionName, AST first) {
+ // locate the registered function by the given name
+ SQLFunction sqlFunction = requireSQLFunction( functionName );
+
+ // determine the type of the first argument...
Type argumentType = null;
- if ( "cast".equals(functionName) ) {
- argumentType = TypeFactory.heuristicType( first.getNextSibling().getText() );
+ if ( first != null ) {
+ if ( "cast".equals(functionName) ) {
+ argumentType = TypeFactory.heuristicType( first.getNextSibling().getText() );
+ }
+ else if ( first instanceof SqlNode ) {
+ argumentType = ( (SqlNode) first ).getDataType();
+ }
}
- else if ( first != null && first instanceof SqlNode ) {
- argumentType = ( (SqlNode) first ).getDataType();
+
+ Type rtnType = sqlFunction.getReturnType( argumentType, sfi );
+ if ( rtnType == null ) {
+ throw new QueryException( "unable to determine function return type [" + functionName + "]" );
}
- // This implementation is a bit strange, but then that's why this helper exists.
- return requireSQLFunction( functionName ).getReturnType( argumentType, sfi );
+
+ return rtnType;
}
public String[][] generateColumnNames(Type[] sqlResultTypes) {
17 years, 5 months
Hibernate SVN: r10819 - branches/Branch_3_2/Hibernate3/src/org/hibernate/type
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-11-16 00:12:20 -0500 (Thu, 16 Nov 2006)
New Revision: 10819
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/type/SerializableType.java
Log:
on second thought...
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/type/SerializableType.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/type/SerializableType.java 2006-11-16 05:12:01 UTC (rev 10818)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/type/SerializableType.java 2006-11-16 05:12:20 UTC (rev 10819)
@@ -45,19 +45,13 @@
}
public boolean isEqual(Object x, Object y) throws HibernateException {
- if (x==y) return true;
- if (x==null || y==null) return false;
- return Hibernate.BINARY.isEqual( toBytes(x), toBytes(y) );
- }
-
- public boolean isDirty(Object old, Object current, SessionImplementor session) throws HibernateException {
- if ( old == current ) {
+ if ( x == y ) {
return true;
}
- if ( old == null || current == null ) {
+ if ( x == null || y == null ) {
return false;
}
- return old.equals( current ) || Hibernate.BINARY.isEqual( toBytes( old ), toBytes( current ) );
+ return x.equals( y ) || Hibernate.BINARY.isEqual( toBytes( x ), toBytes( y ) );
}
public int getHashCode(Object x, EntityMode entityMode) {
17 years, 5 months
Hibernate SVN: r10818 - trunk/Hibernate3/src/org/hibernate/type
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-11-16 00:12:01 -0500 (Thu, 16 Nov 2006)
New Revision: 10818
Modified:
trunk/Hibernate3/src/org/hibernate/type/SerializableType.java
Log:
on second thought...
Modified: trunk/Hibernate3/src/org/hibernate/type/SerializableType.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/type/SerializableType.java 2006-11-15 19:47:44 UTC (rev 10817)
+++ trunk/Hibernate3/src/org/hibernate/type/SerializableType.java 2006-11-16 05:12:01 UTC (rev 10818)
@@ -45,19 +45,13 @@
}
public boolean isEqual(Object x, Object y) throws HibernateException {
- if (x==y) return true;
- if (x==null || y==null) return false;
- return Hibernate.BINARY.isEqual( toBytes(x), toBytes(y) );
- }
-
- public boolean isDirty(Object old, Object current, SessionImplementor session) throws HibernateException {
- if ( old == current ) {
+ if ( x == y ) {
return true;
}
- if ( old == null || current == null ) {
+ if ( x == null || y == null ) {
return false;
}
- return old.equals( current ) || Hibernate.BINARY.isEqual( toBytes( old ), toBytes( current ) );
+ return x.equals( y ) || Hibernate.BINARY.isEqual( toBytes( x ), toBytes( y ) );
}
public int getHashCode(Object x, EntityMode entityMode) {
17 years, 5 months
Hibernate SVN: r10817 - branches/Branch_3_2/Hibernate3/src/org/hibernate/type
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-11-15 14:47:44 -0500 (Wed, 15 Nov 2006)
New Revision: 10817
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/type/SerializableType.java
Log:
minor change to how SerializableType determines dirtiness
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/type/SerializableType.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/type/SerializableType.java 2006-11-15 19:47:22 UTC (rev 10816)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/type/SerializableType.java 2006-11-15 19:47:44 UTC (rev 10817)
@@ -50,6 +50,16 @@
return Hibernate.BINARY.isEqual( toBytes(x), toBytes(y) );
}
+ public boolean isDirty(Object old, Object current, SessionImplementor session) throws HibernateException {
+ if ( old == current ) {
+ return true;
+ }
+ if ( old == null || current == null ) {
+ return false;
+ }
+ return old.equals( current ) || Hibernate.BINARY.isEqual( toBytes( old ), toBytes( current ) );
+ }
+
public int getHashCode(Object x, EntityMode entityMode) {
return Hibernate.BINARY.getHashCode( toBytes(x), entityMode );
}
17 years, 5 months
Hibernate SVN: r10816 - trunk/Hibernate3/src/org/hibernate/type
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2006-11-15 14:47:22 -0500 (Wed, 15 Nov 2006)
New Revision: 10816
Modified:
trunk/Hibernate3/src/org/hibernate/type/SerializableType.java
Log:
minor change to how SerializableType determines dirtiness
Modified: trunk/Hibernate3/src/org/hibernate/type/SerializableType.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/type/SerializableType.java 2006-11-15 15:27:54 UTC (rev 10815)
+++ trunk/Hibernate3/src/org/hibernate/type/SerializableType.java 2006-11-15 19:47:22 UTC (rev 10816)
@@ -50,6 +50,16 @@
return Hibernate.BINARY.isEqual( toBytes(x), toBytes(y) );
}
+ public boolean isDirty(Object old, Object current, SessionImplementor session) throws HibernateException {
+ if ( old == current ) {
+ return true;
+ }
+ if ( old == null || current == null ) {
+ return false;
+ }
+ return old.equals( current ) || Hibernate.BINARY.isEqual( toBytes( old ), toBytes( current ) );
+ }
+
public int getHashCode(Object x, EntityMode entityMode) {
return Hibernate.BINARY.getHashCode( toBytes(x), entityMode );
}
17 years, 5 months
Hibernate SVN: r10815 - trunk/Hibernate3/doc/reference
by hibernate-commits@lists.jboss.org
Author: caoxg
Date: 2006-11-15 10:27:54 -0500 (Wed, 15 Nov 2006)
New Revision: 10815
Modified:
trunk/Hibernate3/doc/reference/build.xml
Log:
Hibernate 3.2 Simplified Chinese Reference is ready.
Modified: trunk/Hibernate3/doc/reference/build.xml
===================================================================
--- trunk/Hibernate3/doc/reference/build.xml 2006-11-15 15:21:02 UTC (rev 10814)
+++ trunk/Hibernate3/doc/reference/build.xml 2006-11-15 15:27:54 UTC (rev 10815)
@@ -40,8 +40,8 @@
<!-- TRANSLATOR: Duplicate this line for your language -->
<antcall target="lang.all"><param name="lang" value="en"/></antcall>
+ <antcall target="lang.all"><param name="lang" value="zh-cn"/></antcall>
<!-- TODO: These translations need updating...
- <antcall target="lang.all"><param name="lang" value="zh-cn"/></antcall>
<antcall target="lang.all"><param name="lang" value="es"/></antcall>
<antcall target="lang.all"><param name="lang" value="ja"/></antcall>
<antcall target="lang.all"><param name="lang" value="fr"/></antcall>
17 years, 5 months
Hibernate SVN: r10814 - trunk/Hibernate3/doc/reference/zh-cn
by hibernate-commits@lists.jboss.org
Author: caoxg
Date: 2006-11-15 10:21:02 -0500 (Wed, 15 Nov 2006)
New Revision: 10814
Added:
trunk/Hibernate3/doc/reference/zh-cn/README_CHINESE_FONT.txt
Log:
README about how to compile PDF with windows fonts.
Added: trunk/Hibernate3/doc/reference/zh-cn/README_CHINESE_FONT.txt
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/README_CHINESE_FONT.txt 2006-11-15 15:16:57 UTC (rev 10813)
+++ trunk/Hibernate3/doc/reference/zh-cn/README_CHINESE_FONT.txt 2006-11-15 15:21:02 UTC (rev 10814)
@@ -0,0 +1,6 @@
+Please be noticed that to build the pdf in Simplified Chinese, you need SimHei.ttf and SimSun.ttf from windows system, which can be found at \Windows\Fonts.
+Please copy these 2 files into fop folder before build.
+
+Thanks!
+
+Xiaogang Cao.
\ No newline at end of file
17 years, 5 months