KickJava   Java API By Example, From Geeks To Geeks.

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


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: SyncMapping.java,v 1.3 2005/03/02 20:57:38 harrie Exp $
38  */

39 public class SyncMapping 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 SyncMapping(final SyncHdr syncHeader, final SyncBody syncBody) throws Sync4jException {
97         super(syncHeader, syncBody);
98         checkHeaderRequirements();
99         checkBodyRequirements();
100     }
101
102     /**
103      * Checks that all requirements regarding the header of the initialization
104      * packet are respected.
105      *
106      * @throws ProtocolException
107      */

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

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

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

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

174     public SyncML getResponseMessage(String JavaDoc msgId)
175     throws ProtocolException {
176         SyncHdr responseHeader = getResponseHeader(msgId);
177         AbstractCommand[] commands =
178             (AbstractCommand[]) getResponseCommands(msgId).toArray(new AbstractCommand[0]);
179         SyncBody responseBody = new SyncBody(
180             commands,
181             isFlag(Flags.FLAG_FINAL_MESSAGE)
182         );
183
184         try {
185             return new SyncML(responseHeader, responseBody);
186         } catch (RepresentationException e) {
187             //
188
// It should never happen !!!!
189
//
190
throw new ProtocolException("Unexpected error", e);
191         }
192     }
193     
194     /**
195      * Returns the response commands in response to the incoming mapping
196      * message.
197      *
198      * @param msgId the message id to use
199      *
200      * @return an array of AbstractCommand
201      *
202      * @throws ProtocolException in case of errors
203      */

204     public List JavaDoc getResponseCommands( String JavaDoc msgId)
205     throws ProtocolException {
206         ArrayList JavaDoc commands = new ArrayList JavaDoc();
207
208         /*
209         2. The Status element(s) MUST be included in SyncBody. It is now used to indicate the status of
210           the Map operation(s). This or these can be sent before Package #5 is completely received.
211         */

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

239             Status mapStatus = null;
240             for (int i=0; i<mapCommands.length; ++i) {
241
242                 targetRefs = new TargetRef[] { new TargetRef(mapCommands[i].getTarget()) };
243                 sourceRefs = new SourceRef[] { new SourceRef(mapCommands[i].getSource()) };
244
245                 mapStatus = new Status(
246                     idGenerator.next(),
247                     lastMessageId,
248                     mapCommands[i].getCmdID().getCmdID(),
249                     Map.COMMAND_NAME,
250                     targetRefs,
251                     sourceRefs,
252                     null,
253                     null,
254                     new Data(StatusCode.OK),
255                     new Item[0]
256                 );
257                 commands.add(mapStatus);
258             }
259         }
260
261         return commands;
262     }
263     
264     /**
265      * Returns the response SyncHdr to return in response of the incoming SyncML
266      * message.
267      *
268      * @param msgId the message id to use
269      *
270      * @return the SyncHdr object
271      *
272      * @thorws ProtocolException in case of errors
273      */

274     public SyncHdr getResponseHeader(String JavaDoc msgId)
275     throws ProtocolException {
276         /*
277         1. Requirements for the elements within the SyncHdr element.
278             - The value of the VerDTD element MUST be '1.1'.
279             - The value of the VerProto element MUST be 'SyncML/1.1'.
280             - Session ID MUST be included to indicate the ID of a sync session.
281             - MsgID MUST be used to unambiguously identify the message belonging a sync session
282               and traveling from the client to the server.
283             - The Target element MUST be used to identify the target device and service.
284             - The Source element MUST be used to identify the source device.
285             - The response MUST NOT be required for this message.
286         */

287         Target target = new Target(syncHeader.getSource().getLocURI(),
288                                    syncHeader.getSource().getLocName());
289         Source source = new Source(syncHeader.getTarget().getLocURI(),
290                                    syncHeader.getTarget().getLocName());
291         SyncHdr responseHeader = new SyncHdr(
292                 getDTDVersion() ,
293                 getProtocolVersion() ,
294                 syncHeader.getSessionID(),
295                 msgId ,
296                 target ,
297                 source ,
298                 null /* response URI */ ,
299                 false /* Response not required */ ,
300                 null /* credentials */ ,
301                 null /* meta date */
302         );
303         
304         return responseHeader;
305
306     }
307 }
308
309
Popular Tags