001: /**
002: * Copyright (C) 2001-2004 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.generation.mivisitor;
018:
019: import org.objectweb.speedo.lib.Personality;
020: import org.objectweb.speedo.metadata.SpeedoClass;
021: import org.objectweb.speedo.metadata.SpeedoField;
022: import org.objectweb.speedo.api.SpeedoException;
023: import org.objectweb.speedo.api.SpeedoProperties;
024: import org.objectweb.speedo.generation.enhancer.common.AbstractEnhancerComponent;
025: import org.objectweb.speedo.generation.enhancer.common.LoggedClassVisitor;
026: import org.objectweb.speedo.generation.enhancer.common.Util;
027: import org.objectweb.speedo.generation.api.SpeedoCompilerParameter;
028: import org.objectweb.util.monolog.api.Logger;
029: import org.objectweb.util.monolog.api.BasicLevel;
030: import org.objectweb.asm.ClassVisitor;
031: import org.objectweb.asm.CodeVisitor;
032: import org.objectweb.asm.Constants;
033: import org.objectweb.asm.Type;
034: import org.objectweb.asm.Attribute;
035:
036: import java.util.Collection;
037: import java.util.Iterator;
038: import java.util.List;
039: import java.util.ArrayList;
040:
041: /**
042: *
043: * @author S.Chassande-Barrioz
044: */
045: public class PrimaryKeyFieldAdder extends AbstractMetaInfoVisitor {
046: private Loader loader;
047:
048: public PrimaryKeyFieldAdder(Personality p) {
049: super (p);
050: loader = new Loader(p);
051: }
052:
053: public PrimaryKeyFieldAdder(MetaInfoVisitor mim, Personality p) {
054: super (mim, p);
055: loader = new Loader(p);
056: }
057:
058: private class Loader extends AbstractEnhancerComponent {
059:
060: public Loader(Personality p) {
061: super (p);
062: }
063:
064: public boolean init() throws SpeedoException {
065: isSrcJar = false;
066: return true;
067: }
068:
069: public void process() throws SpeedoException {
070: //nothing
071: }
072:
073: public void setLogger(Logger logger) {
074: this .logger = logger;
075: }
076: }
077:
078: protected String getLoggerName() {
079: return SpeedoProperties.LOGGER_NAME
080: + ".generation.enhancer.analyzer";
081: }
082:
083: public void setLogger(Logger logger) {
084: super .setLogger(logger);
085: loader.setLogger(logger);
086: }
087:
088: public void visitCompilerParameter(SpeedoCompilerParameter scp)
089: throws SpeedoException {
090: loader.setSpeedoCompilerParameter(scp);
091: super .visitCompilerParameter(scp);
092: }
093:
094: public void visitClass(SpeedoClass sc) throws SpeedoException {
095: super .visitClass(sc);
096: List pkfields = sc.getPKFields();
097: if (sc.identity.objectidClass == null) {
098: return;
099: }
100: logger.log(BasicLevel.DEBUG, "PrimaryKeyFieldAdder.visitClass("
101: + sc.getFQName() + ")");
102: boolean isSrcJar = false;
103: SpeedoCompilerParameter _scp = loader
104: .getSpeedoCompilerParameter();
105: String className = sc.identity.objectidClass;
106: if (className.indexOf('.') == -1) {
107: className = sc.moPackage.name + '.' + className;
108: }
109: UserIDClassAnalyzer uica = new UserIDClassAnalyzer(logger);
110: loader.loadJavaClass(isSrcJar, className, _scp.output, false)
111: .accept(uica, true);
112: if (uica.fieldNames.isEmpty()) {
113: throw new SpeedoException("The identifier class '"
114: + sc.identity.objectidClass
115: + "' has no public field.");
116: }
117: if (sc.getSuperClassName() != null) {
118: //do nothing, the primary key field are inherited from the ancestor
119: } else if (pkfields.isEmpty()) {
120: for (int i = 0; i < uica.fieldNames.size(); i++) {
121: SpeedoField sf = (SpeedoField) sc.fields
122: .get(uica.fieldNames.get(i));
123: if (sf == null) {
124: logger
125: .log(
126: BasicLevel.WARN,
127: "The public field '"
128: + uica.fieldNames.get(i)
129: + "' of the identifier class "
130: + className
131: + "' does not match to any field in the persistent class '"
132: + sc.getFQName() + "'.");
133: continue;
134: }
135: if (!sf.type.equals(uica.fieldTypes.get(i))) {
136: throw new SpeedoException(
137: "The field '"
138: + sf.name
139: + "' has not the same type in identifier class '"
140: + className
141: + "' ("
142: + Util
143: .type(Type
144: .getType((String) uica.fieldTypes
145: .get(i)))
146: + ") and in the persistent class '"
147: + sc.getFQName() + "' ("
148: + Util.type(Type.getType(sf.type))
149: + ").");
150: }
151: sf.primaryKey = true;
152: }
153: } else {
154: //check that the lists are the same
155: for (int i = 0; i < pkfields.size(); i++) {
156: if (!uica.fieldNames.contains(((SpeedoField) pkfields
157: .get(i)).name)) {
158: logger.log(BasicLevel.ERROR, "uica.fieldNames:\n"
159: + uica.fieldNames);
160: logger.log(BasicLevel.ERROR, "pkfields:\n"
161: + pkfields);
162: throw new SpeedoException(
163: "The field '"
164: + pkfields.get(i)
165: + "' is marked primary-key=true whereas it is not "
166: + "defined in the identifier class '"
167: + className
168: + "' associated to the persistent class '"
169: + sc.getFQName() + "'.");
170: }
171: }
172: }
173: }
174:
175: private static class UserIDClassAnalyzer extends LoggedClassVisitor
176: implements ClassVisitor {
177:
178: public List fieldNames;
179: public List fieldTypes;
180:
181: public UserIDClassAnalyzer(Logger logger) {
182: super (logger);
183: fieldNames = new ArrayList();
184: fieldTypes = new ArrayList();
185: }
186:
187: public void visit(int version, int i, String s, String s1,
188: String[] strings, String s2) {
189: }
190:
191: public void visitInnerClass(String s, String s1, String s2,
192: int i) {
193: }
194:
195: public void visitField(final int access, final String name,
196: final String desc, final Object value,
197: final Attribute attrs) {
198: if ((access & Constants.ACC_PUBLIC) != 0) {
199: fieldNames.add(name);
200: fieldTypes.add(desc);
201: }
202: }
203:
204: public CodeVisitor visitMethod(int i, String s, String s1,
205: String[] strings, Attribute attrs) {
206: return null;
207: }
208:
209: public void visitAttribute(Attribute attribute) {
210: }
211:
212: public void visitEnd() {
213: }
214: }
215: }
|