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.cfg21;
031:
032: import com.caucho.ejb.cfg.*;
033: import com.caucho.ejb.cfg21.CmpField;
034: import com.caucho.amber.field.AmberField;
035: import com.caucho.amber.field.EntityManyToManyField;
036: import com.caucho.amber.field.Id;
037: import com.caucho.amber.manager.AmberPersistenceUnit;
038: import com.caucho.amber.table.Column;
039: import com.caucho.amber.table.ForeignColumn;
040: import com.caucho.amber.table.LinkColumns;
041: import com.caucho.amber.table.Table;
042: import com.caucho.amber.type.EntityType;
043: import com.caucho.config.ConfigException;
044: import com.caucho.ejb.ql.QLParser;
045: import com.caucho.util.L10N;
046:
047: import java.util.ArrayList;
048:
049: /**
050: * many-to-many relation
051: */
052: public class CmrManyToMany extends CmrRelation {
053: private static final L10N L = new L10N(CmrManyToMany.class);
054:
055: private String _sqlTable;
056:
057: private EjbEntityBean _targetBean;
058: private String _targetField;
059:
060: // true if the target is only in a single instance
061: private boolean _isTargetUnique;
062:
063: private ArrayList<String> _orderByFields;
064: private ArrayList<Boolean> _orderByAscending;
065:
066: private SqlRelation[] _keySQLColumns;
067: private SqlRelation[] _dstSQLColumns;
068:
069: private EntityManyToManyField _amberManyToMany;
070:
071: /**
072: * Creates a new cmp-relation
073: */
074: public CmrManyToMany(EjbEntityBean entityBean, String fieldName,
075: EjbEntityBean targetBean, String targetField)
076: throws ConfigException {
077: super (entityBean, fieldName);
078:
079: _targetBean = targetBean;
080: _targetField = targetField;
081: }
082:
083: /**
084: * Returns the target bean
085: */
086: public EjbEntityBean getTargetBean() {
087: return _targetBean;
088: }
089:
090: /**
091: * Sets the sql table.
092: */
093: public void setSQLTable(String sqlTable) {
094: _sqlTable = sqlTable;
095: }
096:
097: /**
098: * Gets the sql table.
099: */
100: public String getSQLTable() {
101: if (_sqlTable != null)
102: return _sqlTable;
103: else
104: return getRelationName();
105: }
106:
107: /**
108: * Sets true if the target is unique.
109: */
110: public void setTargetUnique(boolean isUnique) {
111: _isTargetUnique = isUnique;
112: }
113:
114: /**
115: * Sets true if the target is unique.
116: */
117: public boolean isTargetUnique() {
118: return _isTargetUnique;
119: }
120:
121: /**
122: * Returns the target type.
123: */
124: public ApiClass getTargetType() {
125: return _targetBean.getLocal();
126: }
127:
128: /**
129: * Sets the column.
130: */
131: public void setKeySQLColumns(SqlRelation[] columns) {
132: _keySQLColumns = columns;
133: }
134:
135: /**
136: * Gets the column.
137: */
138: public SqlRelation[] getKeySQLColumns() {
139: return _keySQLColumns;
140: }
141:
142: /**
143: * Sets the column.
144: */
145: public void setDstSQLColumns(SqlRelation[] columns) {
146: _dstSQLColumns = columns;
147: }
148:
149: /**
150: * Gets the column.
151: */
152: public SqlRelation[] getDstSQLColumns() {
153: return _dstSQLColumns;
154: }
155:
156: /**
157: * Sets the order by.
158: */
159: public void setOrderBy(String orderBySQL) throws ConfigException {
160: if (orderBySQL != null) {
161: ArrayList<String> fields = new ArrayList<String>();
162: ArrayList<Boolean> asc = new ArrayList<Boolean>();
163:
164: QLParser.parseOrderBy(_targetBean, orderBySQL, fields, asc);
165:
166: _orderByFields = fields;
167: _orderByAscending = asc;
168: }
169: }
170:
171: /**
172: * The OneToMany is a collection.
173: */
174: public boolean isCollection() {
175: return true;
176: }
177:
178: /**
179: * Returns the amber field.
180: */
181: public EntityManyToManyField getAmberField() {
182: return _amberManyToMany;
183: }
184:
185: /**
186: * Create any bean methods.
187: */
188: public EjbMethod createGetter(EjbView view, ApiMethod apiMethod,
189: ApiMethod implMethod) throws ConfigException {
190: return new EjbManyToManyMethod(view, apiMethod, implMethod,
191: this );
192:
193: }
194:
195: /**
196: * Creates the amber type.
197: */
198: public AmberField assembleAmber(EntityType type)
199: throws ConfigException {
200: AmberPersistenceUnit persistenceUnit = type
201: .getPersistenceUnit();
202:
203: Table map = persistenceUnit.createTable(getSQLTable());
204:
205: map.setConfigLocation(getLocation());
206:
207: EntityManyToManyField manyToMany;
208:
209: manyToMany = new EntityManyToManyField(type, getName());
210: _amberManyToMany = manyToMany;
211:
212: manyToMany.setAssociationTable(map);
213:
214: EntityType targetType = _targetBean.getEntityType();
215: manyToMany.setType(targetType);
216:
217: ArrayList<ForeignColumn> targetColumns = calculateColumns(map,
218: targetType, _targetField, _dstSQLColumns);
219:
220: manyToMany.setTargetLink(new LinkColumns(map, targetType
221: .getTable(), targetColumns));
222:
223: EntityType sourceType = getBean().getEntityType();
224: // manyToMany.setType(targetType);
225:
226: ArrayList<ForeignColumn> sourceColumns = calculateColumns(map,
227: sourceType, getName(), _keySQLColumns);
228:
229: manyToMany.setSourceLink(new LinkColumns(map, sourceType
230: .getTable(), sourceColumns));
231:
232: manyToMany.setOrderBy(_orderByFields, _orderByAscending);
233:
234: manyToMany.init();
235:
236: return manyToMany;
237: }
238:
239: private ArrayList<ForeignColumn> calculateColumns(Table mapTable,
240: EntityType type, String fieldName, SqlRelation[] sqlColumns) {
241: ArrayList<ForeignColumn> columns = new ArrayList<ForeignColumn>();
242:
243: Id id = type.getId();
244: ArrayList<Column> keys = id.getColumns();
245:
246: if (sqlColumns != null && sqlColumns.length == keys.size()) {
247: for (int i = 0; i < sqlColumns.length; i++) {
248: ForeignColumn column = mapTable.createForeignColumn(
249: sqlColumns[i].getSQLColumn(), keys.get(i));
250: columns.add(column);
251: }
252: } else if (keys.size() == 1) {
253: Column key = keys.get(0);
254:
255: String sqlColumn;
256:
257: /*
258: if (fieldName != null)
259: sqlColumn = CmpField.toSqlName(type.getName());
260: else
261: sqlColumn = key.getColumn().getName();
262: */
263: if (type.getTable().getName() != null)
264: sqlColumn = type.getTable().getName();
265: else
266: sqlColumn = CmpField.toSqlName(type.getName());
267:
268: columns.add(mapTable.createForeignColumn(sqlColumn, key));
269: } else {
270: String baseSqlColumn;
271:
272: if (sqlColumns != null && sqlColumns.length == 1)
273: baseSqlColumn = sqlColumns[0].getSQLColumn();
274: else
275: baseSqlColumn = type.getTable().getName();
276:
277: if (baseSqlColumn == null)
278: baseSqlColumn = CmpField.toSqlName(type.getName());
279:
280: for (int i = 0; i < keys.size(); i++) {
281: Column key = keys.get(i);
282:
283: String sqlColumn = baseSqlColumn + "_" + key.getName();
284:
285: ForeignColumn foreignColumn = mapTable
286: .createForeignColumn(sqlColumn, key);
287:
288: columns.add(foreignColumn);
289: }
290: }
291:
292: return columns;
293: }
294: }
|