001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.core.cmp.cmp2;
018:
019: import javax.ejb.EJBLocalObject;
020: import javax.ejb.EntityBean;
021: import javax.ejb.EJBException;
022: import javax.transaction.TransactionSynchronizationRegistry;
023: import java.util.Set;
024: import java.util.Iterator;
025: import java.util.Collection;
026: import java.util.ArrayList;
027:
028: import org.apache.openejb.core.CoreDeploymentInfo;
029: import org.apache.openejb.loader.SystemInstance;
030:
031: //
032: // WARNING: Do not refactor this class. It is used by the Cmp2Generator.
033: //
034: public class SetValuedCmr<Bean extends EntityBean, Proxy extends EJBLocalObject> {
035: private final EntityBean source;
036: private final String sourceProperty;
037: private final String relatedProperty;
038: private final CoreDeploymentInfo relatedInfo;
039: private final TransactionSynchronizationRegistry transactionRegistry;
040:
041: public SetValuedCmr(EntityBean source, String sourceProperty,
042: Class<Bean> relatedType, String relatedProperty) {
043: if (source == null)
044: throw new NullPointerException("source is null");
045: if (relatedType == null)
046: throw new NullPointerException("relatedType is null");
047:
048: this .source = source;
049: this .sourceProperty = sourceProperty;
050: this .relatedProperty = relatedProperty;
051:
052: this .relatedInfo = Cmp2Util.getDeploymentInfo(relatedType);
053:
054: transactionRegistry = SystemInstance.get().getComponent(
055: TransactionSynchronizationRegistry.class);
056: }
057:
058: public Set<Proxy> get(Set<Bean> others) {
059: if (sourceProperty == null) {
060: throw new EJBException(
061: "Internal error: this container managed relationship is unidirectional and, "
062: + "this entity does not have a cmr field for the relationship");
063: }
064:
065: if (others == null) {
066: throw new NullPointerException("others is null");
067: }
068:
069: // This may not work if the JPA implementation creates multiple instances in the same tx
070: // in that case we need to key of of the deploymentId, primary key and sourceProperty name
071: CmrSet<Bean, Proxy> cmrSet = null;
072: try {
073: cmrSet = (CmrSet<Bean, Proxy>) transactionRegistry
074: .getResource(this );
075: } catch (IllegalStateException ignored) {
076: // no tx, which is fine
077: }
078:
079: if (cmrSet == null) {
080: cmrSet = new CmrSet<Bean, Proxy>(source, sourceProperty,
081: relatedInfo, relatedProperty, others);
082: try {
083: transactionRegistry.putResource(this , cmrSet);
084: } catch (IllegalStateException ignored) {
085: // we tried but there is no tx
086: }
087: }
088: return cmrSet;
089: }
090:
091: public void set(Set<Bean> relatedBeans, Collection newProxies) {
092: if (sourceProperty == null) {
093: throw new EJBException(
094: "Internal error: this container managed relationship is unidirectional and, "
095: + "this entity does not have a cmr field for the relationship");
096: }
097:
098: // null can not be set into a cmr field
099: // EJB 3.0 Section 8.3.8 "Collections Managed by the Container" bullet 4
100: if (newProxies == null) {
101: throw new IllegalArgumentException(
102: "null can not be set into a collection-valued cmr-field");
103: }
104:
105: // clear back reference in the old related beans
106: if (relatedProperty != null) {
107: for (Bean oldBean : relatedBeans) {
108: if (oldBean != null) {
109: toCmp2Entity(oldBean).OpenEJB_removeCmr(
110: relatedProperty, source);
111: }
112: }
113: }
114: relatedBeans.clear();
115:
116: for (Iterator iterator = new ArrayList(newProxies).iterator(); iterator
117: .hasNext();) {
118: Proxy newProxy = (Proxy) iterator.next();
119: Bean newBean = Cmp2Util.<Bean> getEntityBean(newProxy);
120:
121: if (newProxy != null) {
122: // set the back reference in the new related bean
123: Object oldBackRef = null;
124: if (relatedProperty != null) {
125: oldBackRef = toCmp2Entity(newBean).OpenEJB_addCmr(
126: relatedProperty, source);
127: }
128:
129: // add the bean to our value map
130: relatedBeans.add(newBean);
131:
132: // if the new related beas was related to another bean, we need
133: // to clear the back reference in that old bean
134: if (relatedProperty != null && oldBackRef != null) {
135: toCmp2Entity(oldBackRef).OpenEJB_removeCmr(
136: sourceProperty, newBean);
137: }
138: }
139: }
140: }
141:
142: public void deleted(Set<Bean> relatedBeans) {
143: CmrSet<Bean, Proxy> cmrSet = (CmrSet<Bean, Proxy>) transactionRegistry
144: .getResource(this );
145: if (cmrSet != null) {
146: transactionRegistry.putResource(this , null);
147: cmrSet.entityDeleted();
148: }
149:
150: // clear back reference in the old related beans
151: if (relatedProperty != null) {
152: for (Bean oldBean : relatedBeans) {
153: if (oldBean != null) {
154: toCmp2Entity(oldBean).OpenEJB_removeCmr(
155: relatedProperty, source);
156: }
157: }
158: }
159: }
160:
161: private Cmp2Entity toCmp2Entity(Object object) {
162: return (Cmp2Entity) object;
163: }
164: }
|