0001: /*
0002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License as published by
0011: * the Free Software Foundation; either version 2 of the License, or
0012: * (at your option) any later version.
0013: *
0014: * Resin Open Source is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017: * of NON-INFRINGEMENT. See the GNU General Public License for more
0018: * details.
0019: *
0020: * You should have received a copy of the GNU General Public License
0021: * along with Resin Open Source; if not, write to the
0022: *
0023: * Free Software Foundation, Inc.
0024: * 59 Temple Place, Suite 330
0025: * Boston, MA 02111-1307 USA
0026: *
0027: * @author Scott Ferguson
0028: */
0029:
0030: package com.caucho.amber.field;
0031:
0032: import com.caucho.amber.expr.AmberExpr;
0033: import com.caucho.amber.expr.ManyToOneExpr;
0034: import com.caucho.amber.expr.OneToManyExpr;
0035: import com.caucho.amber.expr.PathExpr;
0036: import com.caucho.amber.query.QueryParser;
0037: import com.caucho.amber.table.LinkColumns;
0038: import com.caucho.amber.table.Table;
0039: import com.caucho.amber.type.RelatedType;
0040: import com.caucho.amber.type.Type;
0041: import com.caucho.bytecode.JField;
0042: import com.caucho.bytecode.JType;
0043: import com.caucho.config.ConfigException;
0044: import com.caucho.java.JavaWriter;
0045: import com.caucho.log.Log;
0046: import com.caucho.util.CharBuffer;
0047: import com.caucho.util.L10N;
0048:
0049: import javax.persistence.CascadeType;
0050: import java.io.IOException;
0051: import java.util.ArrayList;
0052: import java.util.Map;
0053: import java.util.Set;
0054: import java.util.logging.Logger;
0055:
0056: /**
0057: * Configuration for a bean's field
0058: */
0059: public class EntityManyToManyField extends AssociationField {
0060: private static final L10N L = new L10N(EntityManyToManyField.class);
0061: protected static final Logger log = Log
0062: .open(EntityManyToManyField.class);
0063:
0064: private String _mapKey;
0065:
0066: private RelatedType _targetType;
0067:
0068: private Table _associationTable;
0069:
0070: private LinkColumns _sourceLink;
0071: private LinkColumns _targetLink;
0072:
0073: private ArrayList<String> _orderByFields;
0074: private ArrayList<Boolean> _orderByAscending;
0075:
0076: public EntityManyToManyField(RelatedType relatedType, String name,
0077: CascadeType[] cascadeTypes) throws ConfigException {
0078: super (relatedType, name, cascadeTypes);
0079: }
0080:
0081: public EntityManyToManyField(RelatedType relatedType, String name)
0082: throws ConfigException {
0083: this (relatedType, name, null);
0084: }
0085:
0086: public EntityManyToManyField(RelatedType relatedType) {
0087: super (relatedType);
0088: }
0089:
0090: public EntityManyToManyField(RelatedType relatedType, String name,
0091: EntityManyToManyField source, CascadeType[] cascadeTypes)
0092: throws ConfigException {
0093: super (relatedType, name, cascadeTypes);
0094:
0095: _targetType = source.getRelatedType();
0096: _associationTable = source._associationTable;
0097: _sourceLink = source._targetLink;
0098: _targetLink = source._sourceLink;
0099: }
0100:
0101: /**
0102: * Gets the map key.
0103: */
0104: public String getMapKey() {
0105: return _mapKey;
0106: }
0107:
0108: /**
0109: * Sets the map key.
0110: */
0111: public void setMapKey(String mapKey) {
0112: _mapKey = mapKey;
0113: }
0114:
0115: /**
0116: * Sets the target type.
0117: */
0118: public void setType(Type targetType) {
0119: _targetType = (RelatedType) targetType;
0120:
0121: super .setType(targetType);
0122: }
0123:
0124: /**
0125: * Returns the source type as
0126: * entity or mapped-superclass.
0127: */
0128: public RelatedType getRelatedType() {
0129: return (RelatedType) getSourceType();
0130: }
0131:
0132: /**
0133: * Returns the target type.
0134: */
0135: public RelatedType getTargetType() {
0136: return _targetType;
0137: }
0138:
0139: /**
0140: * Returns the association table
0141: */
0142: public Table getAssociationTable() {
0143: return _associationTable;
0144: }
0145:
0146: /**
0147: * Sets the association table
0148: */
0149: public void setAssociationTable(Table table) {
0150: _associationTable = table;
0151: }
0152:
0153: /**
0154: * Adds a column from the association table to the source side.
0155: */
0156: public void setSourceLink(LinkColumns link) {
0157: _sourceLink = link;
0158: }
0159:
0160: /**
0161: * Returns the source link.
0162: */
0163: public LinkColumns getSourceLink() {
0164: return _sourceLink;
0165: }
0166:
0167: /**
0168: * Adds a column from the association table to the target side.
0169: */
0170: public void setTargetLink(LinkColumns link) {
0171: _targetLink = link;
0172: }
0173:
0174: /**
0175: * Returns the target link.
0176: */
0177: public LinkColumns getTargetLink() {
0178: return _targetLink;
0179: }
0180:
0181: /**
0182: * Sets the order by.
0183: */
0184: public void setOrderBy(ArrayList<String> orderByFields,
0185: ArrayList<Boolean> orderByAscending) {
0186: _orderByFields = orderByFields;
0187: _orderByAscending = orderByAscending;
0188: }
0189:
0190: /**
0191: * Initializes the field.
0192: */
0193: public void init() throws ConfigException {
0194: // XXX: might not have cascade delete if there's an associated entity
0195:
0196: _targetLink.setSourceCascadeDelete(true);
0197: _sourceLink.setSourceCascadeDelete(true);
0198: }
0199:
0200: /**
0201: * Generates the set clause.
0202: */
0203: public void generateSet(JavaWriter out, String pstmt, String obj,
0204: String index) throws IOException {
0205: }
0206:
0207: /**
0208: * Generates the select clause.
0209: */
0210: public String generateLoadSelect(String id) {
0211: return null;
0212: }
0213:
0214: /**
0215: * Creates the expression for the field.
0216: */
0217: public AmberExpr createExpr(QueryParser parser, PathExpr parent) {
0218: return new ManyToOneExpr(new OneToManyExpr(parser, parent,
0219: _sourceLink), _targetLink);
0220: }
0221:
0222: /**
0223: * Updates from the cached copy.
0224: */
0225: public void generateCopyLoadObject(JavaWriter out, String dst,
0226: String src, int loadIndex) throws IOException {
0227: // jpa/0s2j
0228: if (dst.equals("item"))
0229: return;
0230:
0231: String var = "_caucho_field_" + getGetterName();
0232:
0233: // order matters: jpa/0s2k
0234: String value = var; // generateGet(src);
0235: out.println(generateSet(dst, value) + ";");
0236:
0237: out.println(generateAccessor(dst, var) + " = "
0238: + generateAccessor(src, var) + ";");
0239:
0240: if (!dst.equals("super")) { // || isLazy())) {
0241: String oThis = "(("
0242: + getRelatedType().getInstanceClassName() + ") "
0243: + dst + ")";
0244: out.println(generateSuperSetter(oThis,
0245: generateSuperGetter())
0246: + ";");
0247: }
0248: }
0249:
0250: /**
0251: * Updates the cached copy.
0252: */
0253: public void generateCopyMergeObject(JavaWriter out, String dst,
0254: String src, int updateIndex) throws IOException {
0255: // jpa/0s2k
0256: generateCopyLoadObject(out, dst, src, updateIndex);
0257:
0258: out.println();
0259:
0260: // jpa/0i61
0261: generatePreCascade(out, "aConn", CascadeType.MERGE);
0262: }
0263:
0264: /**
0265: * Generates the target select.
0266: */
0267: public String generateTargetSelect(String id) {
0268: return getTargetType().getId().generateSelect(id);
0269: }
0270:
0271: /**
0272: * Generates the select clause.
0273: */
0274: public String generateTargetLoadSelect(String id) {
0275: CharBuffer cb = CharBuffer.allocate();
0276:
0277: cb.append(getTargetType().getId().generateLoadSelect(id));
0278:
0279: String value = getTargetType().generateLoadSelect(id);
0280:
0281: if (cb.length() > 0 && value.length() > 0)
0282: cb.append(", ");
0283:
0284: cb.append(value);
0285:
0286: return cb.close();
0287: }
0288:
0289: /**
0290: * Generates the set property.
0291: */
0292: public void generateGetProperty(JavaWriter out) throws IOException {
0293: String var = "_caucho_field_" + getGetterName();
0294:
0295: boolean isSet = getJavaType().isAssignableTo(Set.class);
0296: boolean isMap = false;
0297: if (!isSet) {
0298: isMap = getJavaType().isAssignableTo(Map.class);
0299: }
0300:
0301: JType type = getJavaType();
0302: JType[] paramArgs = type.getActualTypeArguments();
0303: JType param = paramArgs.length > 0 ? paramArgs[0] : null;
0304: JType param2 = paramArgs.length > 1 ? paramArgs[1] : null;
0305:
0306: // jpa/0l44
0307: String s = "protected ";
0308:
0309: String collectionImpl;
0310:
0311: if (isSet)
0312: collectionImpl = "com.caucho.amber.collection.SetImpl";
0313: else if (isMap)
0314: collectionImpl = "com.caucho.amber.collection.MapImpl";
0315: else
0316: collectionImpl = "com.caucho.amber.collection.CollectionImpl";
0317:
0318: s = s + collectionImpl;
0319:
0320: if (param != null) {
0321: s = s + '<' + param.getPrintName();
0322: if (isMap) {
0323: if (param2 != null) {
0324: s = s + ", " + param2.getPrintName();
0325: }
0326: }
0327: s = s + '>';
0328: }
0329:
0330: s = s + " " + var;
0331:
0332: // jpa/0i5g
0333: out.println("java.util.HashSet<"
0334: + getTargetType().getBeanClass().getName() + "> " + var
0335: + "_added;");
0336:
0337: out.println();
0338: out.println(s + ';');
0339:
0340: out.println();
0341: out.println("public " + getJavaTypeName() + " "
0342: + getGetterName() + "()");
0343: out.println("{");
0344: out.pushDepth();
0345:
0346: out.println("if (" + var + " != null) {");
0347: out.pushDepth();
0348:
0349: out.println("if (__caucho_state.isPersist()) {");
0350: out.pushDepth();
0351:
0352: out.println(var + ".setSession(__caucho_session);");
0353: out.println("return " + var + ";");
0354:
0355: out.popDepth();
0356: out.println("}");
0357: out.println();
0358:
0359: // jpa/1622
0360: out.println("if (" + var + ".getSession() != null");
0361: out.println(" && " + var
0362: + ".getSession() == __caucho_session)");
0363: out.println(" return " + var + ";");
0364:
0365: out.popDepth();
0366: out.println("}");
0367:
0368: out.println();
0369: out.println("com.caucho.amber.AmberQuery query = null;");
0370:
0371: out.println();
0372: out.println("try {");
0373: out.pushDepth();
0374:
0375: out.println("if (__caucho_session == null) {");
0376: out.pushDepth();
0377:
0378: String newEmptyCollection = "new " + collectionImpl;
0379:
0380: if (param != null) {
0381: newEmptyCollection += "<" + param.getPrintName();
0382: if (isMap) {
0383: newEmptyCollection += ", ";
0384: newEmptyCollection += param2.getPrintName();
0385: }
0386: newEmptyCollection += ">";
0387: }
0388:
0389: newEmptyCollection += "(query";
0390: if (isMap) {
0391: newEmptyCollection += ","
0392: + getTargetType().getBeanClass().getName();
0393: newEmptyCollection += ".class.getDeclaredMethod(\"get";
0394: String getterMapKey = getMapKey();
0395: getterMapKey = Character
0396: .toUpperCase(getterMapKey.charAt(0))
0397: + getterMapKey.substring(1);
0398: newEmptyCollection += getterMapKey; // "getId");
0399: newEmptyCollection += "\", (Class []) null)";
0400: }
0401: newEmptyCollection += ")";
0402:
0403: // jpa/0s2k, jpa/1622
0404: out.println("if (" + var + " == null)");
0405: out.println(" " + var + " = " + newEmptyCollection + ";");
0406:
0407: // if (! isAbstract())
0408: out.println();
0409: out.println("return " + var + ";");
0410:
0411: out.popDepth();
0412: out.println("}");
0413:
0414: out.println();
0415: out.print("String sql=\"");
0416:
0417: out.print("SELECT c");
0418: out.print(" FROM " + getSourceType().getName() + " o,");
0419: out.print(" IN(o." + getName() + ") c");
0420: out.print(" WHERE ");
0421: out.print(getRelatedType().getId().generateRawWhere("o"));
0422:
0423: if (_orderByFields != null) {
0424: out.print(" ORDER BY ");
0425:
0426: for (int i = 0; i < _orderByFields.size(); i++) {
0427: if (i != 0)
0428: out.print(", ");
0429:
0430: out.print("c." + _orderByFields.get(i));
0431: if (Boolean.FALSE.equals(_orderByAscending.get(i)))
0432: out.print(" DESC");
0433: }
0434: }
0435:
0436: out.println("\";");
0437: out.println("query = __caucho_session.prepareQuery(sql);");
0438:
0439: out.println("int index = 1;");
0440: getRelatedType().getId().generateSet(out, "query", "index",
0441: "this");
0442:
0443: // Ex: _caucho_getChildren = new com.caucho.amber.collection.CollectionImpl
0444: out.print(var);
0445: out.print(" = " + newEmptyCollection + ";");
0446:
0447: /*
0448: out.pushDepth();
0449:
0450: generateAdd(out);
0451: generateRemove(out);
0452: generateClear(out);
0453: // generateSize(out);
0454:
0455: out.popDepth();
0456: out.println("};");
0457: */
0458:
0459: out.println();
0460:
0461: // jpa/0i5g
0462: out.print(var + "_added = ");
0463: out.println("new java.util.HashSet<"
0464: + getTargetType().getBeanClass().getName() + ">();");
0465:
0466: if (isMap)
0467: out.print(var + "_added.addAll(" + var + ".values());");
0468: else
0469: out.println(var + "_added.addAll(" + var + ");");
0470:
0471: out.println();
0472: out.println("return " + var + ";");
0473:
0474: out.popDepth();
0475: out.println("} catch (Exception e) {");
0476: out
0477: .println(" throw com.caucho.amber.AmberRuntimeException.create(e);");
0478: out.println("}");
0479:
0480: out.popDepth();
0481: out.println("}");
0482:
0483: generateAmberAdd(out);
0484: generateAmberRemove(out);
0485: generateAmberRemoveTargetAll(out);
0486: }
0487:
0488: /**
0489: * Generates the set property.
0490: */
0491: private void generateAdd(JavaWriter out) throws IOException {
0492: JType type = getJavaType();
0493: JType[] paramArgs = type.getActualTypeArguments();
0494: String gType = paramArgs.length > 0 ? paramArgs[0]
0495: .getPrintName() : "Object";
0496:
0497: out.println("public boolean add(" + gType + " o)");
0498: out.println("{");
0499: out.pushDepth();
0500:
0501: String ownerType = getRelatedType().getInstanceClassName();
0502:
0503: out.println("if (! (o instanceof " + ownerType + "))");
0504: out
0505: .println(" throw new java.lang.IllegalArgumentException((o == null ? \"null\" : o.getClass().getName()) + \" must be a "
0506: + ownerType + "\");");
0507:
0508: out.println(ownerType + " bean = (" + ownerType + ") o;");
0509:
0510: // XXX: makePersistent
0511:
0512: /*
0513: ArrayList<Column> keyColumns = getKeyColumns();
0514: for (int i = 0; i < keyColumns.size(); i++) {
0515: Column column = keyColumns.get(i);
0516: AbstractProperty prop = column.getProperty();
0517:
0518:
0519: if (prop != null) {
0520: out.println("bean." + prop.getSetterName() + "(" + ownerType + "__ResinExt.this);");
0521: }
0522: }
0523: */
0524:
0525: out.println("return true;");
0526:
0527: out.popDepth();
0528: out.println("}");
0529: }
0530:
0531: /**
0532: * Generates the set property.
0533: */
0534: private void generateRemove(JavaWriter out) throws IOException {
0535: JType type = getJavaType();
0536: JType[] paramArgs = type.getActualTypeArguments();
0537: String gType = paramArgs.length > 0 ? paramArgs[0]
0538: .getPrintName() : "Object";
0539:
0540: out.println("public boolean remove(" + gType + " o)");
0541: out.println("{");
0542: out.pushDepth();
0543:
0544: String ownerType = getSourceType().getInstanceClassName();
0545:
0546: out.println("if (! (o instanceof " + ownerType + "))");
0547: out
0548: .println(" throw new java.lang.IllegalArgumentException((o == null ? \"null\" : o.getClass().getName()) + \" must be a "
0549: + ownerType + "\");");
0550:
0551: out.println(ownerType + " bean = (" + ownerType + ") o;");
0552:
0553: // XXX: makePersistent
0554:
0555: /*
0556: ArrayList<Column> keyColumns = getKeyColumns();
0557: for (int i = 0; i < keyColumns.size(); i++) {
0558: Column column = keyColumns.get(i);
0559: AbstractProperty prop = column.getProperty();
0560:
0561: if (prop != null) {
0562: out.println("bean." + prop.getSetterName() + "(null);");
0563: }
0564: }
0565: */
0566:
0567: out.println("return true;");
0568:
0569: out.popDepth();
0570: out.println("}");
0571: }
0572:
0573: /**
0574: * Generates the clear method.
0575: */
0576: private void generateClear(JavaWriter out) throws IOException {
0577: out.println("public void clear()");
0578: out.println("{");
0579: out.pushDepth();
0580:
0581: out.println("if (__caucho_session != null) {");
0582: out.pushDepth();
0583:
0584: out.println("try {");
0585: out.pushDepth();
0586:
0587: out.println("__caucho_session.flushNoChecks();");
0588:
0589: out.print("String sql=\"");
0590:
0591: out.print("UPDATE ");
0592: out.print(getSourceType().getName());
0593: out.print(" SET ");
0594: /*
0595: ArrayList<Column> columns = getKeyColumns();
0596: for (int i = 0; i < columns.size(); i++) {
0597: if (i != 0)
0598: out.print(", ");
0599:
0600: out.print(columns.get(i).getName());
0601: out.print("=null");
0602: }
0603: */
0604:
0605: out.print(" WHERE ");
0606:
0607: /*
0608: for (int i = 0; i < columns.size(); i++) {
0609: if (i != 0)
0610: out.print(" and ");
0611:
0612: out.print(columns.get(i).getName());
0613: out.print("=?");
0614: }
0615: */
0616:
0617: out.println("\";");
0618: out.println("com.caucho.amber.AmberQuery query;");
0619: out.println("query = __caucho_session.prepareQuery(sql);");
0620:
0621: String ownerType = getSourceType().getInstanceClassName();
0622:
0623: out.println("int index = 1;");
0624: getRelatedType().getId().generateSet(out, "query", "index",
0625: ownerType + ".this");
0626:
0627: out.println("query.executeUpdate();");
0628:
0629: out.println("super.clear();");
0630:
0631: out.popDepth();
0632: out.println("} catch (java.sql.SQLException e) {");
0633: out
0634: .println(" throw com.caucho.amber.AmberRuntimeException.create(e);");
0635: out.println("}");
0636:
0637: out.popDepth();
0638: out.println("} else {");
0639: out.println(" super.clear();");
0640: out.println("}");
0641:
0642: out.popDepth();
0643: out.println("}");
0644: }
0645:
0646: /**
0647: * Generates the size method.
0648: */
0649: private void generateSize(JavaWriter out) throws IOException {
0650: out.println("public int size()");
0651: out.println("{");
0652: out.pushDepth();
0653:
0654: out.println("if (__caucho_session == null || isValid())");
0655: out.println(" return super.size();");
0656:
0657: out.println("try {");
0658: out.pushDepth();
0659:
0660: out.println("__caucho_session.flushNoChecks();");
0661:
0662: out.print("String sql=\"");
0663:
0664: out.print("SELECT count(*) FROM ");
0665: out.print(getSourceType().getName());
0666: out.print(" AS o ");
0667:
0668: out.print(" WHERE ");
0669:
0670: /*
0671: ArrayList<Column> columns = getKeyColumns();
0672: for (int i = 0; i < columns.size(); i++) {
0673: if (i != 0)
0674: out.print(" and ");
0675:
0676: out.print("o." + columns.get(i).getName());
0677: out.print("=?");
0678: }
0679: */
0680:
0681: out.println("\";");
0682: out.println("com.caucho.amber.AmberQuery query;");
0683: out.println("query = __caucho_session.prepareQuery(sql);");
0684:
0685: out.println("int index = 1;");
0686:
0687: // ejb/06h0
0688: getRelatedType().getId().generateSet(out, "query",
0689: getSourceType().getInstanceClassName() + ".this",
0690: "index"); // "__ResinExt.this", "index");
0691:
0692: out.println("java.sql.ResultSet rs = query.executeQuery();");
0693:
0694: out.println("if (rs.next())");
0695: out.println(" return rs.getInt(1);");
0696: out.println("else");
0697: out.println(" return 0;");
0698:
0699: out.popDepth();
0700: out.println("} catch (java.sql.SQLException e) {");
0701: out
0702: .println(" throw com.caucho.amber.AmberRuntimeException.create(e);");
0703: out.println("}");
0704:
0705: out.popDepth();
0706: out.println("}");
0707: }
0708:
0709: /**
0710: * Generates the (post) cascade operation from
0711: * parent to this child. This field will only
0712: * be cascaded first if the operation can be
0713: * performed with no risk to break FK constraints.
0714: */
0715: public void generatePostCascade(JavaWriter out, String aConn,
0716: CascadeType cascadeType) throws IOException {
0717: if (cascadeType != CascadeType.PERSIST
0718: && cascadeType != CascadeType.REMOVE)
0719: return;
0720:
0721: if (isCascade(cascadeType)) {
0722: out
0723: .println("if (__caucho_state.ordinal() <= com.caucho.amber.entity.EntityState.P_TRANSACTIONAL.ordinal()) {");
0724: out.pushDepth();
0725:
0726: String amberCascade = "__amber_" + getGetterName();
0727:
0728: if (cascadeType == CascadeType.PERSIST)
0729: amberCascade += "_add";
0730: else
0731: amberCascade += "_remove";
0732:
0733: String getter = "_caucho_field_" + getGetterName(); // generateSuperGetter();
0734:
0735: out.println("if (" + getter + " != null) {");
0736: out.pushDepth();
0737:
0738: if (cascadeType == CascadeType.PERSIST) {
0739: // XXX: jpa/0i5c
0740: // For now, needs to flush the persist() with many-to-many
0741: // to avoid breaking FK constraints from join tables.
0742: out
0743: .println("if (__caucho_state == com.caucho.amber.entity.EntityState.P_PERSISTING)");
0744: out
0745: .println(" __caucho_create(__caucho_session, __caucho_home);");
0746: }
0747:
0748: out.println();
0749: out.println("for (Object o : " + getter + ") {");
0750: out.pushDepth();
0751:
0752: if (cascadeType == CascadeType.PERSIST) {
0753: // jpa/0i60
0754: out
0755: .println("((com.caucho.amber.entity.Entity) o).__caucho_flush();");
0756:
0757: // jpa/1622
0758: out.println(amberCascade + "(aConn, o);");
0759: } else
0760: out.println(amberCascade + "(o);");
0761:
0762: out.popDepth();
0763: out.println("}");
0764:
0765: out.popDepth();
0766: out.println("}");
0767:
0768: out.popDepth();
0769: out.println("}");
0770: }
0771: }
0772:
0773: /**
0774: * Generates the set property.
0775: */
0776: public void generateAmberAdd(JavaWriter out) throws IOException {
0777: // commented out: jpa/0s2d
0778: // String targetType = getTargetType().getProxyClass().getName();
0779:
0780: String targetType = getTargetType().getInstanceClassName();
0781:
0782: out.println();
0783: out
0784: .println("public boolean"
0785: + " __amber_"
0786: + getGetterName()
0787: + "_add(com.caucho.amber.manager.AmberConnection aConn, Object o)");
0788: out.println("{");
0789: out.pushDepth();
0790:
0791: out.println("if (! (o instanceof " + targetType + "))");
0792: out.println(" return false;");
0793:
0794: out.println();
0795: out.println(targetType + " v = (" + targetType + ") o;");
0796:
0797: // jpa/0i5g
0798: String varAdded = "_caucho_field_" + getGetterName() + "_added";
0799: out.println();
0800: out.println("if (" + varAdded + " == null)");
0801: out.println(" " + varAdded + " = new java.util.HashSet<"
0802: + getTargetType().getBeanClass().getName() + ">();");
0803: out.println("else if (" + varAdded + ".contains(v))");
0804: out.println(" return false;");
0805: out.println();
0806: out.println(varAdded + ".add(v);");
0807:
0808: out.println();
0809: out.println("if (aConn == null)");
0810: out.println(" return false;");
0811:
0812: out.println();
0813: out.print("String sql = \"INSERT INTO ");
0814: out.print(_associationTable.getName() + " (");
0815:
0816: out.print(_sourceLink.generateSelectSQL(null));
0817:
0818: out.print(", ");
0819:
0820: out.print(_targetLink.generateSelectSQL(null));
0821:
0822: out.print(") VALUES (");
0823:
0824: int count = (getRelatedType().getId().getKeyCount() + getTargetType()
0825: .getId().getKeyCount());
0826:
0827: for (int i = 0; i < count; i++) {
0828: if (i != 0)
0829: out.print(", ");
0830:
0831: out.print("?");
0832: }
0833: out.println(")\";");
0834:
0835: out.println();
0836: out.println("try {");
0837: out.pushDepth();
0838:
0839: out
0840: .println("java.sql.PreparedStatement pstmt = aConn.prepareInsertStatement(sql);");
0841:
0842: out.println("int index = 1;");
0843: getRelatedType().getId().generateSet(out, "pstmt", "index",
0844: "this");
0845: getTargetType().getId().generateSet(out, "pstmt", "index", "v");
0846:
0847: out.println("if (pstmt.executeUpdate() == 1) {");
0848: out.pushDepth();
0849: out
0850: .println("aConn.addCompletion(new com.caucho.amber.entity.TableInvalidateCompletion(\""
0851: + _targetLink.getSourceTable().getName()
0852: + "\"));");
0853: out.println("return true;");
0854: out.popDepth();
0855: out.println("}");
0856:
0857: out.popDepth();
0858: out.println("} catch (Exception e) {");
0859: out
0860: .println(" __caucho_log.log(java.util.logging.Level.FINE, e.toString(), e);");
0861: out.println("}");
0862:
0863: out.println("return false;");
0864: out.popDepth();
0865: out.println("}");
0866: }
0867:
0868: /**
0869: * Generates the remove property.
0870: */
0871: public void generateAmberRemove(JavaWriter out) throws IOException {
0872: // commented out: jpa/0s2d
0873: // String targetType = getTargetType().getProxyClass().getName();
0874:
0875: String targetType = getTargetType().getInstanceClassName();
0876:
0877: out.println();
0878: out.println("public boolean" + " __amber_" + getGetterName()
0879: + "_remove(Object o)");
0880: out.println("{");
0881: out.pushDepth();
0882:
0883: out.println("if (! (o instanceof " + targetType + "))");
0884: out.println(" return false;");
0885:
0886: out.println();
0887: out.println(targetType + " v = (" + targetType + ") o;");
0888: out.println();
0889: out.println("if (__caucho_session == null)");
0890: out.println(" return false;");
0891:
0892: out.println();
0893: out.print("String sql = \"DELETE FROM ");
0894: out.print(_associationTable.getName() + " WHERE ");
0895:
0896: out.print(_sourceLink.generateMatchArgSQL(null));
0897:
0898: out.print(" and ");
0899:
0900: out.print(_targetLink.generateMatchArgSQL(null));
0901:
0902: out.println("\";");
0903:
0904: out.println();
0905: out.println("try {");
0906: out.pushDepth();
0907:
0908: out
0909: .println("java.sql.PreparedStatement pstmt = __caucho_session.prepareStatement(sql);");
0910:
0911: out.println("int index = 1;");
0912: getRelatedType().getId().generateSet(out, "pstmt", "index",
0913: "this");
0914: getTargetType().getId().generateSet(out, "pstmt", "index", "v");
0915:
0916: out.println("if (pstmt.executeUpdate() == 1) {");
0917: out.pushDepth();
0918: out
0919: .println("__caucho_session.addCompletion(new com.caucho.amber.entity.TableInvalidateCompletion(\""
0920: + _targetLink.getSourceTable().getName()
0921: + "\"));");
0922: out.println("return true;");
0923: out.popDepth();
0924: out.println("}");
0925:
0926: out.popDepth();
0927: out.println("} catch (Exception e) {");
0928: out
0929: .println(" __caucho_log.log(java.util.logging.Level.FINE, e.toString(), e);");
0930: out.println("}");
0931:
0932: out.println("return false;");
0933: out.popDepth();
0934: out.println("}");
0935: }
0936:
0937: /**
0938: * Generates the remove property.
0939: */
0940: public void generateAmberRemoveTargetAll(JavaWriter out)
0941: throws IOException {
0942: // commented out: jpa/0s2d
0943: // String targetType = getTargetType().getProxyClass().getName();
0944:
0945: String targetType = getTargetType().getInstanceClassName();
0946:
0947: out.println();
0948: out.println("public boolean" + " __amber_" + getGetterName()
0949: + "_remove_target(Object o)");
0950: out.println("{");
0951: out.pushDepth();
0952:
0953: out.println("if (! (o instanceof " + targetType + "))");
0954: out.println(" return false;");
0955:
0956: out.println();
0957: out.println(targetType + " v = (" + targetType + ") o;");
0958: out.println();
0959: out.println("if (__caucho_session == null)");
0960: out.println(" return false;");
0961:
0962: out.println();
0963: out.print("String sql = \"DELETE FROM ");
0964: out.print(_associationTable.getName() + " WHERE ");
0965:
0966: out.print(_targetLink.generateMatchArgSQL(null));
0967:
0968: out.println("\";");
0969:
0970: out.println();
0971: out.println("try {");
0972: out.pushDepth();
0973:
0974: out
0975: .println("java.sql.PreparedStatement pstmt = __caucho_session.prepareStatement(sql);");
0976:
0977: out.println("int index = 1;");
0978: getTargetType().getId().generateSet(out, "pstmt", "index", "v");
0979:
0980: out.println("if (pstmt.executeUpdate() == 1)");
0981: out.println(" return true;");
0982:
0983: out.popDepth();
0984: out.println("} catch (Exception e) {");
0985: out
0986: .println(" __caucho_log.log(java.util.logging.Level.FINE, e.toString(), e);");
0987: out.println("}");
0988:
0989: out.println("return false;");
0990: out.popDepth();
0991: out.println("}");
0992: }
0993:
0994: /**
0995: * Generates the set property.
0996: */
0997: public void generateSetProperty(JavaWriter out) throws IOException {
0998: // commented out: jpa/0s2i
0999: // JMethod setter = getSetterMethod();
1000: //
1001: // if (setter == null)
1002: // return;
1003: //
1004: // JType type = getGetterMethod().getGenericReturnType();
1005:
1006: JType type;
1007:
1008: if (!getSourceType().isFieldAccess()) {
1009: type = getGetterMethod().getGenericReturnType();
1010: } else {
1011: JField field = RelatedType.getField(getBeanClass(),
1012: getName());
1013: type = field.getGenericType();
1014: }
1015:
1016: out.println();
1017: // commented out: jpa/0s2i
1018: // out.print("public void " + setter.getName() + "(");
1019: out.print("public void " + getSetterName() + "(");
1020: out.println(type.getPrintName() + " value)");
1021: out.println("{");
1022: out.pushDepth();
1023:
1024: out.println("if (" + generateSuperGetter() + " == value)");
1025: out.println(" return;");
1026: out.println();
1027:
1028: //
1029: // jpa/0s2j needs to generate the following snippet:
1030: //
1031: // _caucho___caucho_get_xAnnualReviews
1032: // = new com.caucho.amber.collection.CollectionImpl<qa.XAnnualReview>(__caucho_session, null);
1033: // _caucho___caucho_get_xAnnualReviews.addAll(0, value);
1034: //
1035: //
1036: // jpa/0s2j:
1037:
1038: out.println("try {");
1039: out.pushDepth();
1040:
1041: String var = "_caucho_field_" + getGetterName();
1042:
1043: out.print(var + " = new ");
1044:
1045: type = getJavaType();
1046:
1047: boolean isSet = type.isAssignableTo(Set.class);
1048: boolean isMap = false;
1049: if (!isSet) {
1050: isMap = type.isAssignableTo(Map.class);
1051: }
1052:
1053: JType[] paramArgs = type.getActualTypeArguments();
1054: JType param = paramArgs.length > 0 ? paramArgs[0] : null;
1055: JType param2 = paramArgs.length > 1 ? paramArgs[1] : null;
1056:
1057: String collectionImpl;
1058:
1059: if (isSet)
1060: collectionImpl = "com.caucho.amber.collection.SetImpl";
1061: else if (isMap)
1062: collectionImpl = "com.caucho.amber.collection.MapImpl";
1063: else
1064: collectionImpl = "com.caucho.amber.collection.CollectionImpl";
1065:
1066: out.print(collectionImpl);
1067:
1068: if (param != null) {
1069: out.print("<");
1070: out.print(param.getPrintName());
1071: if (isMap) {
1072: if (param2 != null) {
1073: out.print(", ");
1074: out.print(param2.getPrintName());
1075: }
1076: }
1077: out.print(">");
1078: }
1079:
1080: out.print("(__caucho_session, null");
1081: if (isMap) {
1082: out.print(", ");
1083: out.print(getTargetType().getBeanClass().getName());
1084: out.print(".class.getDeclaredMethod(\"get");
1085: String getterMapKey = getMapKey();
1086: getterMapKey = Character
1087: .toUpperCase(getterMapKey.charAt(0))
1088: + getterMapKey.substring(1);
1089: out.print(getterMapKey); // "getId");
1090: out.print("\")");
1091: }
1092: out.println(");");
1093:
1094: out.print(var + ".");
1095:
1096: if (isMap) {
1097: out.println("putAll(value);");
1098: } else {
1099: out.println("addAll(0, value);");
1100: }
1101:
1102: out.popDepth();
1103: out.println("} catch(Exception e) {");
1104: out
1105: .println(" throw com.caucho.amber.AmberRuntimeException.create(e);");
1106: out.println("}");
1107:
1108: out.popDepth();
1109: out.println("}");
1110: }
1111:
1112: /**
1113: * Generates code for foreign entity create/delete
1114: */
1115: public void generateInvalidateForeign(JavaWriter out)
1116: throws IOException {
1117: out.println("if (\"" + _sourceLink.getSourceTable().getName()
1118: + "\".equals(table)) {");
1119: out.pushDepth();
1120:
1121: generateExpire(out);
1122:
1123: out.popDepth();
1124: out.println("}");
1125: }
1126:
1127: /**
1128: * Generates code for the object expire
1129: */
1130: public void generateExpire(JavaWriter out) throws IOException {
1131: String var = "_caucho_field_" + getGetterName();
1132:
1133: out.println("if (" + var + " != null)");
1134: out.println(" " + var + ".update();");
1135: }
1136:
1137: private String generateAccessor(String src, String var) {
1138: if (src.equals("super"))
1139: return var;
1140: else
1141: return "((" + getRelatedType().getInstanceClassName()
1142: + ") " + src + ")." + var;
1143: }
1144: }
|