KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > applications > dove > AbstractDove


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10
11 package org.mmbase.applications.dove;
12
13 import java.util.*;
14 import org.w3c.dom.*;
15 import org.mmbase.util.logging.*;
16 import org.mmbase.bridge.Cloud;
17
18
19 /**
20  * This class handles Remote Procedure Calls described using a DOM model.
21  * The original data is received in xml, likely through a specialized servlet such
22  * as the DoveServlet (but this is not required. it may, for instance, be
23  * possible to use this class in conjunction with SOAP or even outside a servlet
24  * context).
25  * The call should result in a new DOM tree (see the EditWizard API for details).
26  * <br />
27  * XXX: Currently, this class performs some type of validation on the xml received.
28  * If errors occur, they are included in the response, at the place where they
29  * occur. This means that the &lt;error &gt; tag can occur anywhere in the
30  * response, which is not very neat.
31  * <br />
32  * Errors have three types:<br />
33  * parser : the xml given is invalid or does not follow the grammar.
34  * This likely means there is a bug in the client code.<br />
35  * server : the code invoked is either not yet implemented or another,
36  * server-related, error occurred (such as no memory, bad configuration,
37  * etc.).
38  * Server errors entirely fail a request.<br />
39  * client : The data requested could not be retrieved or values specified
40  * were invalid. I.e. a requested node does not exist (any more), or a
41  * <code>put</code> failed due to locking or invalid data.<br />
42  * <br />
43  * This is ONLY for debugging purposes!
44  * XML validation should occur at the parser and be captured early.
45  * If we reach consensus that we must always validate, the xml-checking can be left
46  * out, as we can then assumes a correct model. This will optimize processing.
47  *
48  * @author Pierre van Rooden
49  * @since MMBase-1.5
50  * @version $Id: AbstractDove.java,v 1.20 2006/04/24 12:06:07 michiel Exp $
51  */

52
53 public abstract class AbstractDove {
54
55     // dtds
56
public static final String JavaDoc DOCTYPE_REQUEST = "http://www.mmbase.org/dtd/doverequest_1_1.dtd";
57     public static final String JavaDoc DOCTYPE_RESPONSE = "http://www.mmbase.org/dtd/doveresponse_1_2.dtd";
58
59     // keywords used for tags
60
public static final String JavaDoc REQUEST = "request";
61     public static final String JavaDoc RESPONSE = "response";
62
63     public static final String JavaDoc SECURITY = "security";
64     public static final String JavaDoc GETDATA = "getdata";
65     public static final String JavaDoc GETNEW = "getnew";
66     public static final String JavaDoc GETNEWRELATION = "getnewrelation";
67     public static final String JavaDoc GETRELATIONS = "getrelations";
68     public static final String JavaDoc GETCONSTRAINTS = "getconstraints";
69     public static final String JavaDoc GETLIST = "getlist";
70     public static final String JavaDoc PUT = "put";
71
72     public static final String JavaDoc SECURITY_NAME = "name";
73     public static final String JavaDoc SECURITY_PASSWORD = "password";
74     public static final String JavaDoc SECURITY_CLOUD = "cloud";
75     public static final String JavaDoc SECURITY_METHOD = "method";
76
77     public static final String JavaDoc OBJECT = "object"; // confusing?
78
public static final String JavaDoc FIELD = "field";
79     public static final String JavaDoc ORIGINAL = "original";
80     public static final String JavaDoc NEW = "new";
81     public static final String JavaDoc RELATIONS = "relations";
82     public static final String JavaDoc RELATION = "relation";
83     public static final String JavaDoc ERROR = "error";
84     public static final String JavaDoc QUERY = "query";
85     public static final String JavaDoc PARENT = "parent";
86     public static final String JavaDoc DESCENDANTS = "descendants";
87     public static final String JavaDoc DESCENDANT = "descendant";
88
89     public static final String JavaDoc SINGULARNAME = "singularname";
90     public static final String JavaDoc PLURALNAME = "pluralname";
91     public static final String JavaDoc DESCRIPTION = "description";
92     public static final String JavaDoc FIELDS = "fields";
93     public static final String JavaDoc GUINAME = "guiname";
94     public static final String JavaDoc GUITYPE = "guitype";
95     public static final String JavaDoc MAXLENGTH = "maxlength";
96     public static final String JavaDoc REQUIRED = "required";
97
98     // keywords used for attributes
99
public static final String JavaDoc ELM_ID = "id";
100     public static final String JavaDoc ELM_NUMBER = "number";
101     public static final String JavaDoc ELM_OLDNUMBER = "oldnumber";
102     public static final String JavaDoc ELM_TYPE = "type";
103     public static final String JavaDoc ELM_STATUS = "status";
104     public static final String JavaDoc ELM_NAME = "name";
105     public static final String JavaDoc ELM_ROLE = "role";
106     public static final String JavaDoc ELM_DESTINATION = "destination";
107     public static final String JavaDoc ELM_DESTINATIONTYPE = "destinationtype";
108     public static final String JavaDoc ELM_SOURCETYPE = "sourcetype";
109     public static final String JavaDoc ELM_SEARCHDIR = "searchdir";
110     public static final String JavaDoc ELM_CREATEDIR = "createdir";
111     public static final String JavaDoc ELM_LANG = "xml:lang";
112     public static final String JavaDoc ELM_XPATH = "xpath";
113     public static final String JavaDoc ELM_WHERE = "where";
114     public static final String JavaDoc ELM_ORDERBY = "orderby";
115     public static final String JavaDoc ELM_DIRECTIONS = "directions";
116     public static final String JavaDoc ELM_SOURCE = "source";
117     public static final String JavaDoc ELM_HREF = "href";
118     public static final String JavaDoc ELM_MAYWRITE = "maywrite";
119     public static final String JavaDoc ELM_MAYDELETE = "maydelete";
120     public static final String JavaDoc ELM_CONTEXT = "context";
121     public static final String JavaDoc ELM_SIZE = "size";
122     public static final String JavaDoc ELM_ENCODING = "encoding";
123
124     // values
125
public static final String JavaDoc IS_PARSER = "parser";
126     public static final String JavaDoc IS_SERVER = "server";
127     public static final String JavaDoc IS_CLIENT = "client";
128
129     public static final String JavaDoc IS_TRUE = "true";
130     public static final String JavaDoc IS_FALSE = "false";
131
132     protected final static String JavaDoc[] TYPE_DESCRIPTIONS = {
133         "unknown", "string", "integer", "unknown", "byte", "float", "double", "long", "xml", "node", "datetime", "boolean", "list"
134     };
135
136     //logger
137
private static final Logger log = Logging.getLoggerInstance(Dove.class);
138
139     /**
140      * The document that is being constructed. This should be used to
141      * construct new DOM elements.
142      */

143     protected Document doc = null;
144
145     /**
146      * Constructor
147      * @param doc the Document that is constructed. This should only be used to
148      * construct new DOM elements. New (child) nodes should not be added
149      * to this document, but to the out element.
150      */

151     public AbstractDove(Document doc) {
152         this.doc=doc;
153     }
154
155     protected String JavaDoc getTypeDescription(int type) {
156        if (type >= 0 && type < TYPE_DESCRIPTIONS.length) {
157             return TYPE_DESCRIPTIONS[type];
158        } else {
159             return TYPE_DESCRIPTIONS[0];
160        }
161     }
162
163     /**
164      * Creates a DOM element which contains a Text Node, and adds it to the
165      * specified node as a child.
166      * Used for creating field and error tags.
167      * @param tagname name of the new element
168      * @param content content of the new element as a string
169      * @param out the element to which to add the new Element.
170      * @return the newly created element
171      */

172     protected Element addContentElement(String JavaDoc tagname,String JavaDoc content, Element out) {
173         Element el=doc.createElement(tagname);
174         if (content==null) content="";
175         Text tel=doc.createTextNode(content);
176         el.appendChild(tel);
177         out.appendChild(el);
178         return el;
179     }
180
181     /**
182      * Retrieves the first child node of an element that is itself an element.
183      * If none exist, it returns <code>null</code>.
184      * @param item the element to find the first child element of
185      * @return the first child element, or <code>null</code>.
186      */

187     protected Element getFirstElement(Node item) {
188         if (item==null) return null;
189         item=item.getFirstChild();
190         if ((item!=null) && !(item instanceof Element)) {
191             item = getNextElement(item);
192         };
193         return (Element)item;
194     }
195
196     /**
197      * Retrieves the first child node of an element that is itself an element, and has the specified tagname.
198      * If none exist, it returns <code>null</code>.
199      * @param item the element to find the first child element of
200      * @param tagname the tagname of the element desired
201      * @return the first child element, or <code>null</code>.
202      */

203     protected Element getFirstElement(Node item, String JavaDoc tagname) {
204         Element elm=getFirstElement(item);
205         if (elm!=null && !elm.getTagName().equals(tagname)) {
206             elm=getNextElement(elm,tagname);
207         }
208         return elm;
209     }
210
211     /**
212      * Retrieves the next sibling of an element that is itself an element.
213      * If none exist, it returns <code>null</code>.
214      * @param item the element to find the sibling element of
215      * @return the sibling element, or <code>null</code>.
216      */

217     protected Element getNextElement(Node item) {
218         if (item==null) return null;
219         do {
220             item=item.getNextSibling();
221         } while ((item!=null) && !(item instanceof Element));
222         return (Element)item;
223     }
224
225     /**
226      * Retrieves the the next sibling of an element that is itself an element, and has the specified tagname.
227      * If none exist, it returns <code>null</code>.
228      * @param item the element to find the sibling element of
229      * @param tagname the tagname of the element desired
230      * @return the first child element, or <code>null</code>.
231      */

232     protected Element getNextElement(Node item, String JavaDoc tagname) {
233         Element elm=getNextElement(item);
234         while (elm!=null && !elm.getTagName().equals(tagname)) {
235             elm=getNextElement(elm);
236         }
237         return elm;
238     }
239
240
241     /**
242      * Handles a request running one or more RPCs.
243      * This method accepts a root DOM element, which should contain as it
244      * child nodes elements describing the call(s) to perform.
245      * Each element is an xml element with as the tagname the name of the
246      * call to run. Valid calls are getdata, getrelations, getlist, getconstraints,
247      * getnew, and put.
248      * The calls are redirected to the appropriate encapsulating method in
249      * this class. The end result of each call should be a DOM tree, built
250      * using the given parameters, which is then appended to the out element.
251      * <br />
252      * XXX:This method runs all commands in order of entrance. It does
253      * not currently check whether all child nodes refer to the same call.
254      * This means that it is possible to mix 'getdata' and 'getrelations' calls
255      * in one request. Ina dditon, it ignores calls it does not know how to handle.
256      * as described above, this should be handled by the xml parser.
257      * Note also that if no id was given for a call, a NullPointer exception is thrown.
258      *
259      * @param in the element that described the request (or input).
260      * The childnodes should describe the calls to perform.
261      * @param out the element that described the response (or return value).
262      * Results of calls should be added as childs to this element.
263      * @param cloud the MMCI cloud to use, if applicable.
264      * @param repository Repository that contains the blobs
265      */

266     public abstract void doRequest(Element in, Element out, Cloud cloud, Map repository);
267
268     /**
269      * Handles a request running one or more RPCs.
270      * @param in the element that described the request (or input).
271      * The childnodes should describe the calls to perform.
272      * @param out the element that described the response (or return value).
273      * Results of calls should be added as childs to this element.
274      */

275     public void doRequest(Element in, Element out) {
276         doRequest(in, out, null, null);
277     }
278
279     /**
280      * This method executes the request from the editors, it can be invoked directly
281      * @param in the element that described the request (or input).
282      * The childnodes should describe the calls to perform.
283      * @param cloud the MMCI cloud to use, if applicable.
284      * @param repository Repository that contains the blobs
285      * @return the element that described the response (or return value).
286      * Results of calls should be added as childs to this element.
287      */

288     public Element executeRequest (Element in, Cloud cloud, Map repository) {
289         Element out =doc.createElement(RESPONSE);
290         doc.appendChild(out);
291         if (in.getTagName().equals(REQUEST)) {
292             doRequest(in,out,cloud, repository);
293             return out;
294         }
295         log.error("Request doesn't contain a <REQUEST> tag.");
296         Element err=addContentElement(ERROR,"Request doesn't contain a <REQUEST> tag.",out);
297         err.setAttribute(ELM_TYPE,IS_CLIENT);
298         return out;
299     }
300
301
302     /**
303      * This method executes the request from the editors, it can be invoked directly
304      * @param in the element that described the request (or input).
305      * The childnodes should describe the calls to perform.
306      * @return the element that described the response (or return value).
307      * Results of calls should be added as childs to this element.
308      */

309     public Element executeRequest (Element in) {
310         return executeRequest(in,null,null);
311     }
312 }
313
314
Popular Tags