KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > framework > protocol > ClientCompletion


1 /**
2  * Copyright (C) 2003-2005 Funambol
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package sync4j.framework.protocol;
19
20 import sync4j.framework.core.*;
21 import sync4j.framework.protocol.v11.BasicRequirements;
22 import sync4j.framework.protocol.ProtocolUtil;
23 import sync4j.framework.logging.Sync4jLogger;
24
25 import java.util.List JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28
29 /**
30  * ClientCompletion class represent the phase or state that come after
31  * Modification phase. In this state client send status for the sync command,
32  * a status for every sub sync command like Add, Replace and finally send a
33  * MapCommand in the case a AddCommand was done succesfully.
34  * We need to extract this mapping information to update the LUID GUID Mapping.
35  * see the SyncML sync protocol for a detailed example
36  *
37  * @version $Id: ClientCompletion.java,v 1.1 2005/05/16 17:32:55 nichele Exp $
38  */

39 public class ClientCompletion extends SyncPackage {
40
41     /**
42      * Sync4j Logging facility
43      */

44     private transient Logger mLog = Sync4jLogger.getLogger();
45
46     /**
47      * Cache the commands sent by the client. It is set during the
48      * check for the requirements.
49      */

50     private AbstractCommand[] clientCommands = null;
51
52     /**
53      * Get all the commands extracted from the client last message.
54      * @return An array of AbstractCommand
55      */

56     public AbstractCommand[] getClientCommands() {
57         return clientCommands;
58     }
59
60     /**
61      * The Map Command from the client. It's used to construct the
62      * response back to client.
63      */

64     private Map[] mapCommands = null;
65
66     /**
67      * Get the Map command
68      */

69     public Map[] getMapCommands() {
70         return mapCommands;
71     }
72
73     /**
74      * true if Map Command where find
75      */

76     private boolean mapCommandFind = false;
77
78     /**
79      * @return true if a map Command were find
80      */

81     public boolean isMapCommandFind() {
82         return mapCommandFind;
83     }
84
85     /**
86      * The last message from client Identifier.
87      */

88     private String JavaDoc lastMessageId = null;
89
90     /**
91      * Contruct a ClientCompletion State processing treatment
92      * @param syncHeader The header of the client message
93      * @param syncBody The body of the client message
94      * @throws Sync4jException
95      */

96     public ClientCompletion(final SyncHdr syncHeader, final SyncBody syncBody)
97     throws ProtocolException {
98         super(syncHeader, syncBody);
99         checkHeaderRequirements();
100         checkBodyRequirements();
101     }
102
103     /**
104      * Checks that all requirements regarding the header of the initialization
105      * packet are respected.
106      *
107      * @throws ProtocolException
108      */

109     public void checkHeaderRequirements() throws ProtocolException {
110         BasicRequirements.checkDTDVersion(syncHeader.getVerDTD());
111         BasicRequirements.checkProtocolVersion(syncHeader.getVerProto());
112         BasicRequirements.checkSessionId(syncHeader.getSessionID());
113         BasicRequirements.checkMessageId(syncHeader.getMsgID());
114         BasicRequirements.checkTarget(syncHeader.getTarget());
115         BasicRequirements.checkSource(syncHeader.getSource());
116
117         //Conserve the message ID from the client message header.
118
lastMessageId = syncHeader.getMsgID();
119     }
120
121     /**
122      * Checks that all requirements regarding the body of the initialization
123      * packet are respected.
124      *
125      * @throws ProtocolException
126      */

127     public void checkBodyRequirements() throws ProtocolException {
128         clientCommands = (AbstractCommand[])syncBody.getCommands().toArray(new AbstractCommand[0]);
129
130         // Check the status command if add ak then check for map command
131
checkStatusCommands();
132
133         //If status for AddCommand was find
134
checkMapCommand();
135     }
136
137     /**
138      * Check the status commands from the client to check failure and to check
139      * wether or not a status from a Add Command Exist. In this case true is
140      * return to toggle the Map existence.
141      * todo : check the failure
142      */

143     private void checkStatusCommands() {
144     }
145
146     /**
147      * Check The Map Command for new mapped items.
148      * @throws ProtocolException
149      */

150     private void checkMapCommand() throws ProtocolException {
151         List JavaDoc list = ProtocolUtil.filterCommands(clientCommands, Map.class);
152
153         if (list.size() > 0) {
154             mapCommands = (Map[]) list.toArray(new Map[list.size()]);
155             mapCommandFind = true;
156         } else {
157             mapCommands = null;
158             mapCommandFind = false;
159         }
160     }
161
162     /**
163      * Constructs a proper response message. That include from the syncMl spec
164      * <br>
165      * <ui>
166      * <li>Status for last message syncheader</li>
167      * <li>May include Status for the mapping command</li>
168      * <ui>
169      *
170      * @param msgId the msg id of the response
171      * @return the response message
172      * @throws ProtocolException in case of error or inconsistency
173      */

174     public SyncML getResponse(String JavaDoc msgId) throws ProtocolException {
175         ArrayList JavaDoc commands = new ArrayList JavaDoc();
176
177         /*
178         1. Requirements for the elements within the SyncHdr element.
179             - The value of the VerDTD element MUST be '1.1'.
180             - The value of the VerProto element MUST be 'SyncML/1.1'.
181             - Session ID MUST be included to indicate the ID of a sync session.
182             - MsgID MUST be used to unambiguously identify the message belonging a sync session
183               and traveling from the client to the server.
184             - The Target element MUST be used to identify the target device and service.
185             - The Source element MUST be used to identify the source device.
186             - The response MUST NOT be required for this message.
187         */

188         Target target = new Target(syncHeader.getSource().getLocURI(),
189                                    syncHeader.getSource().getLocName());
190         Source source = new Source(syncHeader.getTarget().getLocURI(),
191                                    syncHeader.getTarget().getLocName());
192         SyncHdr responseHeader = new SyncHdr(
193             getDTDVersion() ,
194             getProtocolVersion() ,
195             syncHeader.getSessionID() ,
196             msgId ,
197             target ,
198             source ,
199             null /* response URI */ ,
200             false /* Response not required */,
201             null /* credentials */ ,
202             null /* meta date */
203         );
204
205         /*
206         2. The Status element(s) MUST be included in SyncBody. It is now used to indicate the status of
207           the Map operation(s). This or these can be sent before Package #5 is completely received.
208         */

209         //
210
// Create the synhdr status response
211
//
212
TargetRef[] targetRefs = new TargetRef[] { new TargetRef(syncHeader.getTarget().getLocURI()) };
213         SourceRef[] sourceRefs = new SourceRef[] { new SourceRef(syncHeader.getSource().getLocURI()) };
214
215         Status synchdrStatus = new Status(
216             idGenerator.next(),
217             lastMessageId,
218             "0",
219             "SyncHdr",
220             targetRefs,
221             sourceRefs,
222             null,
223             null,
224             new Data(StatusCode.OK),
225             new Item[0]
226         );
227         commands.add(synchdrStatus);
228
229         //
230
//Create the map commands status response
231
//
232
if (mapCommandFind) {
233             //Contruct the status command for the Map command
234

235             Status mapStatus = null;
236             for (int i=0; i<mapCommands.length; ++i) {
237
238                 targetRefs = new TargetRef[] { new TargetRef(mapCommands[i].getTarget()) };
239                 sourceRefs = new SourceRef[] { new SourceRef(mapCommands[i].getSource()) };
240
241                 mapStatus = new Status(
242                     idGenerator.next(),
243                     lastMessageId,
244                     mapCommands[i].getCmdID().getCmdID(),
245                     Map.COMMAND_NAME,
246                     targetRefs,
247                     sourceRefs,
248                     null,
249                     null,
250                     new Data(StatusCode.OK),
251                     new Item[0]
252                 );
253                 commands.add(mapStatus);
254             }
255         }
256
257         /*
258         3. The Final element MUST be used for the message, which is the last in this package.
259         */

260         SyncBody responseBody = new SyncBody(
261             (AbstractCommand[]) commands.toArray(new AbstractCommand[0]),
262             isFlag(Flags.FLAG_FINAL_MESSAGE)
263         );
264
265         try {
266             return new SyncML(responseHeader, responseBody);
267         } catch (RepresentationException e) {
268             //
269
// It should never happen !!!!
270
//
271
throw new ProtocolException("Unexpected error", e);
272         }
273     }
274 }
Popular Tags