001: /*
002: * The contents of this file are subject to the
003: * Mozilla Public License Version 1.1 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
009: * See the License for the specific language governing rights and
010: * limitations under the License.
011: *
012: * The Initial Developer of the Original Code is Simulacra Media Ltd.
013: * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
014: *
015: * All Rights Reserved.
016: *
017: * Contributor(s):
018: */
019:
020: package org.openharmonise.dav.server.property.domains;
021:
022: import java.util.*;
023: import java.util.logging.*;
024:
025: import org.openharmonise.commons.dsi.AbstractDataStoreInterface;
026: import org.openharmonise.commons.net.MimeTypeMapping;
027: import org.openharmonise.commons.xml.XMLUtils;
028: import org.openharmonise.commons.xml.namespace.NamespaceType;
029: import org.openharmonise.dav.server.managers.HarmonisePropertiesManager;
030: import org.openharmonise.dav.server.utils.*;
031: import org.openharmonise.rm.*;
032: import org.openharmonise.rm.metadata.Profile;
033: import org.openharmonise.rm.resources.*;
034: import org.openharmonise.rm.resources.content.*;
035: import org.openharmonise.rm.resources.metadata.properties.Property;
036: import org.openharmonise.rm.resources.metadata.properties.domains.Domain;
037: import org.openharmonise.rm.resources.metadata.values.Value;
038: import org.w3c.dom.*;
039: import org.w3c.dom.Document;
040:
041: import com.ibm.webdav.*;
042:
043: /**
044: * This class wraps up the functionality for publishing Harmonise domains to
045: * DAV XML and vice versa.
046: *
047: * @author Michael Bell
048: * @version $Revision: 1.2 $
049: * @since November 19, 2003
050: */
051: public class DAVDomain {
052:
053: public static final String TAG_DOMAIN = "domain";
054: public static final String TAG_MIN_OCCURS = "minOccurs";
055: public static final String TAG_MAX_OCCURS = "maxOccurs";
056: public static final String TYPE_DOMAIN_DATA = "domainData";
057: public static final String TAG_CONTENT_TYPE = "contenttype";
058:
059: private AbstractDataStoreInterface m_dsi = null;
060:
061: /**
062: * Logger for this class
063: */
064: private static final Logger m_logger = Logger
065: .getLogger(DAVDomain.class.getName());
066:
067: /**
068: * List of domains associated to a particular property
069: *
070: */
071: private List m_domain_list = null;
072:
073: /**
074: * Creates an object with a data store interface
075: *
076: * @param dsi
077: */
078: public DAVDomain(AbstractDataStoreInterface dsi) {
079: m_dsi = dsi;
080: }
081:
082: /**
083: * Creates an object with a data store interface and a list of Harmonise domains
084: * which are associated with a property.
085: */
086: public DAVDomain(AbstractDataStoreInterface dsi, List domains) {
087: m_domain_list = domains;
088: m_dsi = dsi;
089:
090: }
091:
092: /**
093: * Returns the current the domain specification of a resource as XML.
094: *
095: * @param doc
096: * @return
097: */
098: public Element asXML(Document doc) throws WebDAVException {
099: Element domainEl = doc.createElementNS(NamespaceType.DAV
100: .getURI(), TAG_DOMAIN);
101: domainEl.setPrefix(NamespaceType.DAV.getPrefix());
102:
103: if (m_domain_list.size() > 1) {
104:
105: domainEl.setAttributeNS(NamespaceType.SOAP_ENCODING
106: .getURI(), NamespaceType.SOAP_ENCODING.getPrefix()
107: + ":"
108: + HarmonisePropertiesManager.ATTRIB_ARRAY_SIZE,
109: String.valueOf(m_domain_list.size()));
110:
111: domainEl
112: .setAttributeNS(
113: NamespaceType.SOAP_ENCODING.getURI(),
114: NamespaceType.SOAP_ENCODING.getPrefix()
115: + ":"
116: + HarmonisePropertiesManager.ATTRIB_ITEM_TYPE,
117: TYPE_DOMAIN_DATA);
118: domainEl.setAttribute("xmlns:"
119: + NamespaceType.SOAP_ENCODING.getPrefix(),
120: NamespaceType.SOAP_ENCODING.getURI());
121:
122: Iterator iter = m_domain_list.iterator();
123:
124: while (iter.hasNext()) {
125: Domain domain = (Domain) iter.next();
126:
127: Element domainDataEl = doc.createElementNS(
128: NamespaceType.DAV.getURI(), TYPE_DOMAIN_DATA);
129:
130: domainDataEl.setPrefix(NamespaceType.DAV.getPrefix());
131: addDomainDetails(domainDataEl, domain, doc);
132:
133: domainEl.appendChild(domainDataEl);
134: }
135:
136: } else if (m_domain_list.size() == 1) {
137:
138: addDomainDetails(domainEl, (Domain) m_domain_list.get(0),
139: doc);
140: }
141:
142: return domainEl;
143: }
144:
145: /**
146: * Adds the domain details to the given domain element.
147: *
148: * @param domainEl
149: * @param doc
150: * @throws WebDAVException
151: */
152: private void addDomainDetails(Element domainEl, Domain domain,
153: Document doc) throws WebDAVException {
154:
155: try {
156: String sDomainObj = domain.getDomainClass();
157:
158: Element resourceTypeEl = doc.createElementNS(
159: NamespaceType.DAV.getURI(),
160: HarmonisePropertiesManager.TAG_RESOURCETYPE);
161: resourceTypeEl.setPrefix(NamespaceType.DAV.getPrefix());
162:
163: String sResourceType = HarmoniseNameResolver
164: .getResourceTypeFromClass(sDomainObj);
165:
166: if (m_logger.isLoggable(Level.FINE)) {
167: m_logger.logp(Level.FINE, this .getClass().getName(),
168: "addDomainDetails", "domain type - "
169: + sResourceType + ", object - "
170: + sDomainObj);
171: }
172:
173: Element resourceEl = doc.createElementNS(NamespaceType.DAV
174: .getURI(), sResourceType);
175: resourceEl.setPrefix(NamespaceType.DAV.getPrefix());
176:
177: resourceTypeEl.appendChild(resourceEl);
178:
179: domainEl.appendChild(resourceTypeEl);
180:
181: int nMinOccurs = domain.getMinOccurs();
182: int nMaxOccurs = domain.getMaxOccurs();
183:
184: if (nMinOccurs > 0) {
185: Element minOccEl = doc.createElementNS(
186: NamespaceType.DAV.getURI(), TAG_MIN_OCCURS);
187: minOccEl.setPrefix(NamespaceType.DAV.getPrefix());
188: minOccEl.appendChild(doc.createTextNode(String
189: .valueOf(nMinOccurs)));
190: domainEl.appendChild(minOccEl);
191: }
192:
193: if (nMaxOccurs > 0) {
194: Element maxOccEl = doc.createElementNS(
195: NamespaceType.DAV.getURI(), TAG_MAX_OCCURS);
196: maxOccEl.setPrefix(NamespaceType.DAV.getPrefix());
197: maxOccEl.appendChild(doc.createTextNode(String
198: .valueOf(nMaxOccurs)));
199: domainEl.appendChild(maxOccEl);
200: }
201:
202: List domainDetails = domain.getDetails();
203:
204: Class domainClass = Class.forName(sDomainObj);
205:
206: if (Profile.class.isAssignableFrom(domainClass)) {
207: domainClass = Property.class;
208: }
209:
210: if (domainDetails.size() > 0) {
211: Iterator detailIter = domainDetails.iterator();
212:
213: while (detailIter.hasNext()) {
214: String sDomainDetails = (String) detailIter.next();
215:
216: String sDAVpath = HarmoniseNameResolver.getDAVPath(
217: domainClass, sDomainDetails);
218:
219: Element hrefEl = doc.createElementNS(
220: NamespaceType.DAV.getURI(),
221: HarmonisePropertiesManager.TAG_HREF);
222: hrefEl.setPrefix(NamespaceType.DAV.getPrefix());
223: hrefEl.appendChild(doc.createTextNode(sDAVpath));
224: domainEl.appendChild(hrefEl);
225: }
226:
227: }
228:
229: List contentRestrictions = domain.getContentRestrictions();
230:
231: Iterator contentIter = contentRestrictions.iterator();
232:
233: while (contentIter.hasNext()) {
234: String sContentType = (String) contentIter.next();
235:
236: Element contentEl = doc.createElementNS(
237: NamespaceType.DAV.getURI(), TAG_CONTENT_TYPE);
238: contentEl.setPrefix(NamespaceType.DAV.getPrefix());
239: contentEl.appendChild(doc.createTextNode(sContentType));
240: domainEl.appendChild(contentEl);
241: }
242:
243: } catch (DataAccessException e) {
244: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
245: throw new WebDAVException(
246: WebDAVStatus.SC_INTERNAL_SERVER_ERROR, e
247: .getLocalizedMessage());
248: } catch (ClassNotFoundException e) {
249: throw new WebDAVException(
250: WebDAVStatus.SC_INTERNAL_SERVER_ERROR, e
251: .getLocalizedMessage());
252: } catch (NameResolverException e) {
253: throw new WebDAVException(
254: WebDAVStatus.SC_INTERNAL_SERVER_ERROR, e
255: .getLocalizedMessage());
256: }
257:
258: }
259:
260: /**
261: * @param propEl
262: */
263: public void populate(Element propEl) throws WebDAVException {
264:
265: if (m_domain_list == null) {
266: m_domain_list = new ArrayList();
267: }
268:
269: NodeList nodes = propEl.getChildNodes();
270:
271: if (nodes.getLength() > 0) {
272: String sArraySize = propEl.getAttributeNS(
273: NamespaceType.SOAP_ENCODING.getURI(),
274: HarmonisePropertiesManager.ATTRIB_ARRAY_SIZE);
275:
276: String sItemType = propEl.getAttributeNS(
277: NamespaceType.SOAP_ENCODING.getURI(),
278: HarmonisePropertiesManager.ATTRIB_ITEM_TYPE);
279:
280: if (sArraySize != null && sArraySize.trim().length() > 0) {
281: NodeList itemNodes = propEl
282: .getElementsByTagName(sItemType);
283:
284: for (int i = 0; i < itemNodes.getLength(); i++) {
285: if (itemNodes.item(i).getNodeType() != Node.ELEMENT_NODE) {
286: continue;
287: }
288: Element tmpEl = (Element) itemNodes.item(i);
289:
290: Domain domain = instantiateDomain(tmpEl);
291:
292: if (domain != null) {
293: m_domain_list.add(domain);
294: } else {
295: throw new WebDAVException(
296: WebDAVStatus.SC_BAD_REQUEST,
297: "Invalid domain spec");
298: }
299: }
300:
301: } else {
302: Domain domain = instantiateDomain(propEl);
303:
304: if (domain != null) {
305: m_domain_list.add(domain);
306: } else {
307: throw new WebDAVException(
308: WebDAVStatus.SC_BAD_REQUEST,
309: "Invalid domain spec");
310: }
311:
312: }
313: }
314: }
315:
316: /**
317: * @return
318: */
319: public List getHarmoniseDomains() {
320: return m_domain_list;
321: }
322:
323: /**
324: * Instantiates a Harmonise domain from the given element.
325: *
326: * @param dataEl
327: * @return
328: * @throws WebDAVException
329: */
330: private Domain instantiateDomain(Element dataEl)
331: throws WebDAVException {
332:
333: Domain domain = new Domain(m_dsi);
334:
335: try {
336:
337: //deal with min and max occurs
338: Element minEl = XMLUtils.getFirstNamedChild(dataEl,
339: TAG_MIN_OCCURS);
340:
341: if (minEl != null) {
342: String sMin = minEl.getChildNodes().item(0)
343: .getNodeValue();
344:
345: domain.setMinOccurs(Integer.parseInt(sMin));
346: }
347:
348: Element maxEl = XMLUtils.getFirstNamedChild(dataEl,
349: TAG_MAX_OCCURS);
350:
351: if (maxEl != null) {
352: String sMax = maxEl.getChildNodes().item(0)
353: .getNodeValue();
354:
355: if (sMax.equalsIgnoreCase("unbounded") == true) {
356: domain.setMaxOccurs(Domain.UNBOUNDED);
357: } else {
358: domain.setMaxOccurs(Integer.parseInt(sMax));
359: }
360: }
361:
362: //get resource type
363: String sResourceType = null;
364:
365: Element resourceEl = XMLUtils.getFirstNamedChild(dataEl,
366: HarmonisePropertiesManager.TAG_RESOURCETYPE);
367:
368: if (resourceEl != null) {
369: Element resourceTypeEl = XMLUtils
370: .getFirstElementChild(resourceEl);
371: sResourceType = resourceTypeEl.getLocalName();
372: }
373:
374: //deal with hrefs
375: NodeList hrefNodes = dataEl.getElementsByTagNameNS(
376: NamespaceType.DAV.getURI(),
377: HarmonisePropertiesManager.TAG_HREF);
378:
379: AbstractChildObject child = null;
380:
381: for (int i = 0; i < hrefNodes.getLength(); i++) {
382: Element hrefEl = (Element) hrefNodes.item(i);
383:
384: String hrefVal = hrefEl.getChildNodes().item(0)
385: .getNodeValue();
386:
387: if (m_logger.isLoggable(Level.FINE)) {
388: m_logger.logp(Level.FINE,
389: this .getClass().getName(),
390: "instantiateDomain", "domain href - "
391: + hrefVal);
392: }
393:
394: child = HarmoniseNameResolver.getObjectFromURL(m_dsi,
395: hrefVal);
396:
397: if (child != null) {
398: domain.addDetails(child.getFullPath());
399: } else {
400: throw new WebDAVException(
401: WebDAVStatus.SC_BAD_REQUEST,
402: "No resource found matching domain");
403: }
404:
405: }
406:
407: //deal with content types
408: NodeList contentNodes = dataEl.getElementsByTagNameNS(
409: NamespaceType.DAV.getURI(), TAG_CONTENT_TYPE);
410: List contentTypes = new Vector();
411:
412: for (int i = 0; i < contentNodes.getLength(); i++) {
413: Element contentEl = (Element) contentNodes.item(i);
414:
415: String contentVal = contentEl.getChildNodes().item(0)
416: .getNodeValue();
417:
418: contentTypes.add(contentVal);
419: domain.addContentTypeRestriction(contentVal);
420:
421: }
422:
423: //set domain obj
424: String sDomainObj = this .getObjectType(
425: (AbstractParentObject) child, sResourceType,
426: contentTypes);
427:
428: Class domainClass = Class.forName(sDomainObj);
429:
430: if (AbstractParentObject.class
431: .isAssignableFrom(domainClass)
432: && domain.getMinOccurs() > 0) {
433: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
434: "Collection domains must have a minoccurs of 0");
435: }
436:
437: if (sDomainObj != null) {
438: domain.setDomainClass(sDomainObj);
439: } else {
440: domain = null;
441: }
442:
443: } catch (ClassNotFoundException e) {
444: throw new WebDAVException(
445: WebDAVStatus.SC_INTERNAL_SERVER_ERROR, e
446: .getLocalizedMessage());
447: } catch (NumberFormatException e) {
448: throw new WebDAVException(
449: WebDAVStatus.SC_INTERNAL_SERVER_ERROR, e
450: .getLocalizedMessage());
451: } catch (PopulateException e) {
452: throw new WebDAVException(
453: WebDAVStatus.SC_INTERNAL_SERVER_ERROR, e
454: .getLocalizedMessage());
455: } catch (DataAccessException e) {
456: throw new WebDAVException(
457: WebDAVStatus.SC_INTERNAL_SERVER_ERROR, e
458: .getLocalizedMessage());
459: } catch (NameResolverException e) {
460: throw new WebDAVException(
461: WebDAVStatus.SC_INTERNAL_SERVER_ERROR, e
462: .getLocalizedMessage());
463: }
464:
465: return domain;
466:
467: }
468:
469: /**
470: * Returns the correct Harmonise object class name given the child object referenced
471: * by the href and the resource type.
472: *
473: * @param child
474: * @param sResourceType
475: * @return
476: */
477: private String getObjectType(AbstractParentObject parent,
478: String sResourceType, List contentTypes)
479: throws DataAccessException {
480: String sObjType = null;
481:
482: String parentName = parent.getClass().getName();
483:
484: if (sResourceType.equals("collection") == true) {
485: sObjType = parentName;
486: } else if (sResourceType.equals("value") == true) {
487: sObjType = Value.class.getName();
488: } else if (sResourceType.equals("property") == true) {
489: sObjType = Profile.class.getName();
490: } else if (sResourceType.equals("property-resource") == true) {
491: sObjType = Property.class.getName();
492: } else {
493: List childClassTypes = parent.getChildClassNames();
494:
495: Iterator iter = childClassTypes.iterator();
496:
497: while (iter.hasNext() && sObjType == null) {
498: String className = (String) iter.next();
499: if (className.equals(parentName) == false) {
500:
501: if (contentTypes == null
502: || contentTypes.size() == 0) {
503: if (parentName.equals(Section.class.getName()) == true) {
504: if (parent.getFullPath().startsWith(
505: HarmoniseNameResolver.ASSETS_PATH)) {
506: sObjType = Asset.class.getName();
507: } else {
508: sObjType = org.openharmonise.rm.resources.content.Document.class
509: .getName();
510: }
511: } else {
512: sObjType = className;
513: }
514:
515: } else {
516: //get class name by content type - should only be needed
517: //for Asset/Document distinction
518: if (parentName.equals(Section.class.getName()) == true) {
519: if (contentTypes.get(0).equals(
520: MimeTypeMapping.XML.getMimeType()) == false
521: || parent
522: .getFullPath()
523: .startsWith(
524: HarmoniseNameResolver.ASSETS_PATH)) {
525: sObjType = Asset.class.getName();
526: } else {
527: sObjType = org.openharmonise.rm.resources.content.Document.class
528: .getName();
529: }
530: }
531: }
532:
533: }
534: }
535:
536: }
537:
538: return sObjType;
539: }
540:
541: }
|