1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.caleigo.core;
20
21 import org.caleigo.core.event.*;
22 import org.caleigo.core.exception.*;
23 import org.caleigo.toolkit.log.*;
24
25
26 /*** <Description for ControledProxyEntity>
27 *
28 * @author Dennis Zikovic
29 * @version 1.00
30 *
31 *//*
32 *
33 * WHEN WHO WHY & WHAT
34 * -----------------------------------------------------------------------------
35 * 2002-04-30 Dennis Zikovic Creation
36 */
37 public class ControlledProxyEntity extends ProxyEntity implements IControlledProxy
38 {
39
40
41
42 private IProxyController mControlEntityProxy;
43 private IEntityRelationPath mRelationPath;
44
45 private Qualifier mRelationQualifier;
46 private IFieldDescriptor[] mReferenceFields;
47 private IFieldDescriptor[] mTargetFields;
48
49 private IEntity mLoadEntity;
50
51
52
53 /*** Creates new ControledSelectionProxy. Note protected scope the class
54 * should normally be instantiated by a call to object impementing the
55 * IProxyController interface and the getControlledProxy method.
56 */
57 protected ControlledProxyEntity(IProxyController controller, IEntityDescriptor entityDescriptor)
58 {
59 this(controller, entityDescriptor, null);
60 }
61
62 /*** Creates new ControledSelectionProxy. Note protected scope the class
63 * should normally be instantiated by a call to object impementing the
64 * IProxyController interface and the getControlledProxy method.
65 */
66 protected ControlledProxyEntity(IProxyController controller, IEntityDescriptor entityDescriptor, IEntityRelationPath relationPath)
67 {
68 super(entityDescriptor);
69
70
71 if(relationPath!=null && !relationPath.isRelatedByPath(controller.getEntityDescriptor(), entityDescriptor))
72 throw new InvalidRelationException("The relation path is not valid for the descriptors "+controller.getEntityDescriptor()+" and "+entityDescriptor);
73
74
75 mControlEntityProxy = controller;
76 if(relationPath!=null)
77 mRelationPath = relationPath;
78 else
79 mRelationPath = this.createRelationPath();
80
81
82 mReferenceFields = new IFieldDescriptor[mRelationPath.getRelation(0).getFieldCount()];
83 mTargetFields = new IFieldDescriptor[mRelationPath.getRelation(0).getFieldCount()];
84 for(int j=0; j<mRelationPath.getRelation(0).getFieldCount(); j++)
85 {
86 mReferenceFields[j] = mRelationPath.getRelation(0).getFieldRelation(j).getReferenceField();
87 mTargetFields[j] = mRelationPath.getRelation(0).getFieldRelation(j).getTargetField();
88 }
89 if(mRelationPath.getRelationCount()>1)
90 {
91 IEntityRelationPath subPath = Relations.getSubRelationPath(mRelationPath, 1);
92 mRelationQualifier = subPath.getRelationQualifier();
93 }
94 else
95 mRelationQualifier = null;
96
97
98 ControllListener listener = new ControllListener();
99 mControlEntityProxy.addProxyListener(listener);
100 mControlEntityProxy.addEntityChangeListener(listener);
101
102
103 this.loadControlledProxies(true);
104 }
105
106
107 protected void loadControlledProxies(boolean includeLocalRemote) throws DataServiceException
108 {
109 IDataTransaction transaction = this.getDataSource().getDataService().newTransaction();
110 if(includeLocalRemote)
111 this.prepareLoad(transaction);
112 else if(this.getSourceEntity()==null)
113 return;
114
115
116 try
117 {
118 AsyncTransactionHandler transactionHandler = AsyncTransactionHandler.create();
119 transactionHandler.setCallback(this, "loadControlledProxiesCallback");
120 if(!transaction.isEmpty())
121 transactionHandler.commit(transaction);
122 else
123 {
124 this.finalizeTransaction(true);
125 this.updateDirtyState();
126 }
127
128
129
130
131
132
133 }
134 catch(DataServiceException e)
135 {
136 this.finalizeTransaction(false);
137 Log.printError(this, "Store transaction failed in proxy controller "+this);
138 throw e;
139 }
140
141 this.updateDirtyState();
142 }
143
144 public void loadControlledProxiesCallback(int status)
145 {
146 if (status == AsyncTransactionHandler.COMMIT_SUCCEEDED)
147 this.finalizeTransaction(true);
148 else
149 this.finalizeTransaction(false);
150
151 this.updateDirtyState();
152 }
153
154
155
156 public IProxyController getController()
157 {
158 return mControlEntityProxy;
159 }
160
161 public IEntityRelationPath getRelationPath()
162 {
163 return mRelationPath;
164 }
165
166 public boolean isEditable()
167 {
168 return true;
169 }
170
171 public void prepareLoad(IDataTransaction transaction)
172 {
173 if(mControlEntityProxy==null || mControlEntityProxy.isEmpty())
174 this.setRemoteEntity(null);
175 else
176 {
177 Qualifier qual = null;
178 if(mTargetFields!=null)
179 {
180 for(int j=0; j<mTargetFields.length; j++)
181 qual = Qualifier.combine(qual, new RelationQualifier(mTargetFields[j], mControlEntityProxy.getData(mReferenceFields[0])));
182 if(mRelationQualifier!=null)
183 qual = qual.and(mRelationQualifier);
184 }
185 else
186 qual = mControlEntityProxy.getOriginQualifier().and(mRelationPath.getRelationQualifier());
187
188 mLoadEntity = this.getEntityDescriptor().createEntity();
189 transaction.addLoad(qual, mLoadEntity);
190 }
191
192
193 this.prepareControlledLoad(transaction);
194 }
195
196 public void prepareStore(IDataTransaction transaction)
197 {
198 if(this.hasRemoteEntity() && this.getRemoteEntity().isDirty())
199 {
200 ITransactionEntityAction action = (ITransactionEntityAction)this.getEntityDescriptor().getAction(IEntityDescriptor.STORE_ACTION);
201 IDataBundle data = action.getDataBundleDescriptor().createActionData();
202 data.setData(0, this.getSourceEntity());
203 action.prepareTransaction(data, transaction);
204 }
205
206
207 this.prepareControlledStore(transaction);
208 }
209
210 /*** The finalizeTransaction method is called after a transaction have been
211 * fully completed. This method will always be called once after any call
212 * to prepareLoad or prepareStore.
213 */
214 public void finalizeTransaction(boolean successful)
215 {
216 super.finalizeTransaction(successful);
217 if(successful)
218 this.setRemoteEntity(mLoadEntity);
219
220 }
221
222
223
224
225
226
227
228
229
230
231 /*** This method is called each time the view entity object are replaced.
232 * It is called prior to doOnControllerDataChange and cand does nothing
233 * by default.
234 */
235 protected void doOnControllerChange()
236 {
237 }
238
239 /*** This method is called each time any data in the viewed entity data are
240 * changed. It is called emidiately after doOnControllerChange and calls
241 * refreshRemoteSelection if any reference fields are changed.
242 */
243 protected void doOnControllerDataChange(IFieldDescriptor fieldDescriptor)
244 {
245 if(mReferenceFields!=null && fieldDescriptor!=null)
246 for(int j=0; j<mReferenceFields.length; j++)
247 if(mReferenceFields[j]==fieldDescriptor)
248 {
249 this.loadControlledProxies(true);
250 return;
251 }
252 }
253
254 /*** Protected help method responsible for creating the relation path
255 * between the master and slave descriptor. The method is only called
256 * if no relation path was provided in the object construction. By default
257 * i creates a new EntityRelationPath with no provided waypoint by it can
258 * be overrriden for more customized bahaviour.
259 */
260 protected IEntityRelationPath createRelationPath()
261 {
262 return EntityRelationPath.create(mControlEntityProxy.getEntityDescriptor(), this.getEntityDescriptor());
263 }
264
265
266
267 protected class ControllListener implements IEntityChangeListener, IProxyListener
268 {
269
270 public void dataChanged(EntityChangeEvent event)
271 {
272 doOnControllerDataChange(event.getFieldDescriptor());
273 }
274
275 public void statusChanged(EntityChangeEvent event)
276 {
277 }
278
279
280 public void remoteChanged(ProxyEvent event)
281 {
282 doOnControllerChange();
283 doOnControllerDataChange(null);
284 }
285
286 public void remoteExpanded(ProxyEvent event)
287 {
288 doOnControllerDataChange(null);
289 }
290 }
291 }