001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.ejb.amber;
031:
032: import com.caucho.ejb.cfg21.EjbEntityBean;
033: import com.caucho.ejb.cfg21.CmrRelation;
034: import com.caucho.ejb.cfg21.CmpProperty;
035: import com.caucho.ejb.cfg21.CmpField;
036: import com.caucho.amber.field.AmberField;
037: import com.caucho.amber.field.CompositeId;
038: import com.caucho.amber.field.Id;
039: import com.caucho.amber.field.IdField;
040: import com.caucho.amber.field.PropertyField;
041: import com.caucho.amber.field.StubMethod;
042: import com.caucho.amber.manager.AmberPersistenceUnit;
043: import com.caucho.amber.table.Column;
044: import com.caucho.amber.table.Table;
045: import com.caucho.amber.type.EntityType;
046: import com.caucho.amber.type.Type;
047: import com.caucho.bytecode.JClassWrapper;
048: import com.caucho.bytecode.JMethodWrapper;
049: import com.caucho.config.ConfigException;
050: import com.caucho.ejb.cfg.*;
051: import com.caucho.java.gen.JavaClassGenerator;
052: import com.caucho.util.L10N;
053: import com.caucho.vfs.PersistentDependency;
054:
055: import java.io.IOException;
056: import java.util.ArrayList;
057: import java.util.HashMap;
058:
059: /**
060: * Configuration manager for amber.
061: */
062: public class AmberConfig {
063: private static final L10N L = new L10N(AmberConfig.class);
064:
065: private EjbConfig _ejbConfig;
066: private AmberPersistenceUnit _manager;
067:
068: private ArrayList<EjbEntityBean> _beans = new ArrayList<EjbEntityBean>();
069:
070: private HashMap<String, EntityType> _entityMap = new HashMap<String, EntityType>();
071:
072: /**
073: * Sets the data source.
074: */
075: public AmberConfig(EjbConfig ejbConfig) {
076: _ejbConfig = ejbConfig;
077: }
078:
079: public void init() throws ConfigException, IOException {
080: }
081:
082: /**
083: * Returns the manager.
084: */
085: public AmberPersistenceUnit getManager() {
086: if (_manager == null)
087: _manager = _ejbConfig.getEjbContainer()
088: .createEjbPersistenceUnit();
089:
090: return _manager;
091: }
092:
093: /**
094: * Adds a new bean config.
095: */
096: public void addBean(EjbEntityBean bean) throws ConfigException {
097: _beans.add(bean);
098:
099: EntityType type = bean.getEntityType();
100:
101: type.setInstanceClassName(bean.getFullImplName());
102: type.setProxyClass(JClassWrapper.create(bean.getLocal()
103: .getJavaClass()));
104:
105: String sqlTable;
106:
107: if (bean.getAbstractSchemaName() != null) {
108: type.setName(bean.getAbstractSchemaName());
109: sqlTable = bean.getAbstractSchemaName();
110: } else {
111: String name = bean.getEJBName();
112: int p = name.lastIndexOf('/');
113: if (p > 0)
114: sqlTable = name.substring(p + 1);
115: else
116: sqlTable = name;
117: }
118:
119: if (bean.getSQLTable() != null)
120: sqlTable = bean.getSQLTable();
121:
122: Table table = getManager().createTable(sqlTable);
123: table.setConfigLocation(bean.getLocation());
124:
125: type.setTable(table);
126:
127: type.setReadOnly(bean.isReadOnly());
128: table.setReadOnly(bean.isReadOnly());
129: type.setCacheTimeout(bean.getCacheTimeout());
130:
131: if (bean.getEJBClassWrapper()
132: .hasMethod("ejbLoad", new Class[0])) {
133: type.setHasLoadCallback(true);
134: }
135:
136: _entityMap.put(bean.getEJBName(), type);
137:
138: ArrayList<CmpProperty> ids = new ArrayList<CmpProperty>();
139:
140: for (CmpField cmpField : bean.getCmpFields()) {
141: if (cmpField.isId())
142: ids.add(cmpField);
143: else
144: configureField(type, cmpField);
145: }
146:
147: for (CmrRelation cmrRelation : bean.getRelations()) {
148: if (cmrRelation.isId())
149: ids.add(cmrRelation);
150: }
151:
152: configureId(bean, type, ids);
153:
154: for (ApiMethod method : bean.getStubMethods()) {
155: type.addStubMethod(new StubMethod(new JMethodWrapper(method
156: .getMethod())));
157: }
158:
159: for (PersistentDependency depend : bean.getDependList()) {
160: type.addDependency(depend);
161: }
162: }
163:
164: /**
165: * Configure the field.
166: */
167: private void configureField(EntityType type, CmpField cmpField)
168: throws ConfigException {
169: String fieldName = cmpField.getName();
170: String sqlName = cmpField.getSQLColumn();
171:
172: if (sqlName == null)
173: sqlName = fieldName;
174:
175: Class dataType = cmpField.getJavaType();
176:
177: if (dataType == null)
178: throw new NullPointerException(L.l(
179: "'{0}' is an unknown field", fieldName));
180:
181: Type amberType = _manager.createType(JClassWrapper
182: .create(dataType));
183: Column column = type.getTable()
184: .createColumn(sqlName, amberType);
185:
186: column.setConfigLocation(cmpField.getLocation());
187:
188: PropertyField field = new PropertyField(type, fieldName);
189: field.setLazy(false);
190: field.setColumn(column);
191:
192: type.addField(field);
193: }
194:
195: /**
196: * Configure the field.
197: */
198: private void configureId(EjbEntityBean bean, EntityType type,
199: ArrayList<CmpProperty> fields) throws ConfigException {
200: ArrayList<IdField> keys = new ArrayList<IdField>();
201:
202: for (CmpProperty cmpProperty : fields) {
203: IdField idField = cmpProperty.createId(_manager, type);
204: if (fields.size() > 1
205: || bean.getCompositeKeyClass() != null)
206: idField.setKeyField(true);
207:
208: keys.add(idField);
209: }
210:
211: if (keys.size() == 1 && bean.getCompositeKeyClass() == null) {
212: Id id = new Id(type, keys.get(0));
213: type.setId(id);
214: } else {
215: CompositeId id = new CompositeId(type, keys);
216: id.setKeyClass(JClassWrapper.create(bean.getPrimKeyClass()
217: .getJavaClass()));
218: type.setId(id);
219: }
220: }
221:
222: public void configureRelations() throws ConfigException {
223: for (EjbEntityBean bean : _beans) {
224: configureRelations(bean);
225: }
226:
227: for (EjbEntityBean bean : _beans) {
228: linkRelations(bean);
229: }
230: }
231:
232: private void configureRelations(EjbEntityBean bean)
233: throws ConfigException {
234: EntityType type = bean.getEntityType();
235:
236: for (CmrRelation rel : bean.getRelations()) {
237: if (!rel.isId())
238: configureRelation(type, rel);
239: }
240: }
241:
242: private void linkRelations(EjbEntityBean bean)
243: throws ConfigException {
244: EntityType type = _entityMap.get(bean.getEJBName());
245:
246: for (CmrRelation rel : bean.getRelations()) {
247: rel.linkAmber();
248: }
249: }
250:
251: /**
252: * Configure the relation rolen.
253: */
254: private void configureRelation(EntityType type, CmrRelation rel)
255: throws ConfigException {
256: String fieldName = rel.getName();
257: String targetName = rel.getTargetBean().getEJBName();
258:
259: EntityType targetType = _entityMap.get(targetName);
260:
261: if (targetType == null)
262: throw new ConfigException(L.l(
263: "'{0}' is an unknown entity type", targetName));
264:
265: AmberField field = rel.assembleAmber(type);
266:
267: if (field != null)
268: type.addField(field);
269: }
270:
271: /**
272: * Generates the beans.
273: */
274: public void generate(JavaClassGenerator javaGen) throws Exception {
275: if (_manager != null)
276: _manager.generate(javaGen);
277: }
278: }
|