/**
* Copyright (C) 2001-2005 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.objectweb.speedo.generation.enhancer.oid;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.speedo.generation.enhancer.common.LoggedClassAdapter;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.speedo.metadata.SpeedoField;
import org.objectweb.speedo.naming.api.UserId;
import org.objectweb.speedo.naming.api.UserIdFactory;
import org.objectweb.util.monolog.api.Logger;
import org.objectweb.util.monolog.api.BasicLevel;
import java.util.Iterator;
/**
* It adds the implementation of the UserIfFactory interface in a PName.
*
* @author S.Chassande-Barrioz
*/
public class PNameEnhancer extends LoggedClassAdapter {
public final static String USER_ID_DESC =
"L" + UserId.class.getName().replace('.', '/') + ";";
public final static String PTYPE_CLASS_NAME =
"org/objectweb/jorm/type/api/PType";
public final static String PTYPE_DESC = "L" + PTYPE_CLASS_NAME + ";";
protected SpeedoClass speedoClass;
public PNameEnhancer(ClassVisitor classVisitor,
SpeedoClass sClass,
Logger logger,
Personality p) {
super(classVisitor, p, logger);
this.speedoClass = sClass;
}
public void visit(final int version, final int access,
final String className,
final String superName,
final String[] interfaces,
final String sourceFile) {
String[] itfs;
String uifcn = UserIdFactory.class.getName().replace('.', '/');
boolean alreadyUIF = false;
if (interfaces == null || interfaces.length==0) {
itfs = new String[]{uifcn};
} else {
int i=0;
while(i<interfaces.length && !interfaces[i].equals(uifcn)) {
i++;
}
alreadyUIF = i<interfaces.length;
if (alreadyUIF) {
itfs = interfaces;
} else {
itfs = new String[interfaces.length + 1];
System.arraycopy(interfaces, 0, itfs, 1, interfaces.length);
itfs[0] = uifcn;
}
}
if (alreadyUIF) {
logger.log(BasicLevel.DEBUG, "The class " + className
+ " already contains the interface " + uifcn);
super.visit(version, access, className, superName, interfaces, sourceFile);
return;
}
logger.log(BasicLevel.DEBUG, "Add to the class " + className
+ " the interface " + uifcn);
super.visit(version, access, className, superName, itfs, sourceFile);
//Add the method getNewUserId
String uicn = speedoClass.identity.objectidClass.replace('.', '/');
String methodName = "getNewUserId";
if (debug) {
logger.log(BasicLevel.DEBUG, "Add the method '" + methodName
+ "' in the class '" + className + "'");
}
logger.log(BasicLevel.DEBUG, "Add to the class " + className
+ " the method " + methodName);
CodeVisitor _cv = this.cv.visitMethod(
Constants.ACC_PUBLIC,
methodName,
"()" + USER_ID_DESC,
null,
null);
// GENERATE: Titi t = new Titi();
// GENERATE: Titi is the class of the user identifier
logger.log(BasicLevel.DEBUG, "add code: " + uicn + " t = new " + uicn + "();");
_cv.visitTypeInsn(Constants.NEW, uicn);
_cv.visitInsn(Constants.DUP);
_cv.visitMethodInsn(Constants.INVOKESPECIAL, uicn, "<init>", "()V");
_cv.visitVarInsn(Constants.ASTORE, 1);
//t.f1 = this.f1
boolean hasLongOrDouble = false;
SpeedoClass current = speedoClass;
while(current != null) {
for(Iterator it = current.fields.values().iterator(); it.hasNext();) {
SpeedoField sp = (SpeedoField) it.next();
if (sp.primaryKey) {
hasLongOrDouble |= sp.type.charAt(0) == 'D'
|| sp.type.charAt(0) == 'J';
logger.log(BasicLevel.DEBUG, "add code: this." + sp.name + " = t." + sp.name);
_cv.visitVarInsn(Constants.ALOAD, 1); //Can be a long|double value
_cv.visitVarInsn(Constants.ALOAD, 0);
_cv.visitFieldInsn(Constants.GETFIELD, className, sp.name, sp.type);
_cv.visitFieldInsn(Constants.PUTFIELD, uicn, sp.name, sp.type);
}
}
SpeedoClass tmp = current.getSuper();
current = (tmp == current ? null : tmp);
}
// GENERATE: t.speedoSetPersistentClassName(this.getPType().getJormName());
logger.log(BasicLevel.DEBUG, "add code: t.speedoSetPersistentClassName(this.getPType().getJormName());");
_cv.visitVarInsn(Constants.ALOAD, 1);
_cv.visitVarInsn(Constants.ALOAD, 0);
_cv.visitMethodInsn(Constants.INVOKEVIRTUAL,
className, "getPType", "()" + PTYPE_DESC);
_cv.visitMethodInsn(Constants.INVOKEVIRTUAL,
PTYPE_CLASS_NAME, "getJormName", "()Ljava/lang/String;");
_cv.visitMethodInsn(Constants.INVOKEVIRTUAL,
uicn, "speedoSetPersistentClassName", "(Ljava/lang/String;)V");
logger.log(BasicLevel.DEBUG, "add code: return t;");
_cv.visitVarInsn(Constants.ALOAD, 1);
_cv.visitInsn(Constants.ARETURN);
_cv.visitMaxs((hasLongOrDouble ? 3 : 2), 2);
}
}