Return-Path: X-Original-To: apmail-abdera-user-archive@www.apache.org Delivered-To: apmail-abdera-user-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9E411EAC8 for ; Tue, 12 Feb 2013 19:47:42 +0000 (UTC) Received: (qmail 23477 invoked by uid 500); 12 Feb 2013 19:47:42 -0000 Delivered-To: apmail-abdera-user-archive@abdera.apache.org Received: (qmail 23396 invoked by uid 500); 12 Feb 2013 19:47:41 -0000 Mailing-List: contact user-help@abdera.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: user@abdera.apache.org Delivered-To: mailing list user@abdera.apache.org Received: (qmail 23383 invoked by uid 99); 12 Feb 2013 19:47:41 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 12 Feb 2013 19:47:41 +0000 X-ASF-Spam-Status: No, hits=-1.6 required=5.0 tests=RCVD_IN_DNSWL_MED,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (nike.apache.org: local policy) Received: from [132.156.238.13] (HELO nrcan.gc.ca) (132.156.238.13) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 12 Feb 2013 19:47:33 +0000 Received: from S-BSC-CAS2.nrn.nrcan.gc.ca (132.156.238.12) by S-BSC-EDGE1.nrcan.gc.ca (132.156.238.13) with Microsoft SMTP Server (TLS) id 14.2.318.4; Tue, 12 Feb 2013 14:47:09 -0500 Received: from S-BSC-MBX1.nrn.nrcan.gc.ca ([169.254.1.98]) by S-BSC-CAS2.nrn.nrcan.gc.ca ([fe80::48d4:f168:78ba:d4e8%19]) with mapi id 14.02.0318.004; Tue, 12 Feb 2013 14:47:09 -0500 From: "Rushforth, Peter" To: "user@abdera.apache.org" Subject: advice: upgrade or work around? Thread-Topic: advice: upgrade or work around? Thread-Index: Ac4JWbyhUREm4C/hQKykXMmjQ3N6tA== Date: Tue, 12 Feb 2013 19:47:07 +0000 Message-ID: <1CD55F04538DEA4F85F3ADF7745464AF2495DE7F@S-BSC-MBX1.nrn.nrcan.gc.ca> Accept-Language: en-CA, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [132.156.238.22] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Virus-Checked: Checked by ClamAV on apache.org Hi There, Thanks for abdera, it is wonderful. =20 I am developing in an abdera 0.3.0 project (atomserver), and I have come ac= ross an issue that is a bit puzzling. I want to add an 'annotated' link element (to a collection element inside t= he feed) which describes our api, but the mere addition of this element is= very slow, so slow that I am wondering if it is a bug somewhere deep insid= e that version of abdera. (I tried the obvious, to upgrade to version 1.1.3 of abdera, but there are = a lot of red lines in my ide after that, so it's a bit daunting). I believe it is my Element getCollectionAPI(RequestContext request) impleme= ntation, with its heavy use of ExtensibleElement, which performs badly, but= I'm not 100% sure. I know for a fact that my getCollection(RequestContext= request) performs badly, based on timings ( 1-10 seconds!). Can you advise what the best path to take is, please? Thanks and cheers, Peter =20 The code which I'm using to add the link element goes like this: public org.apache.abdera.model.Collection getCollection(RequestContext request) { Abdera abdera =3D request.getServiceContext().getAbdera(); AtomWorkspace atomWorkspace =3D this.parentAtomWorkspace; AtomService atomService =3D atomWorkspace.getParentAtomService(); URIHandler uriHandler =3D atomService.getURIHandler(); String workspace =3D atomWorkspace.getName(); String collName =3D this.name; Factory factory =3D AtomServer.getFactory(abdera); org.apache.abdera.model.Collection e =3D factory.newCollection(); TargetType t =3D atomService.getURIHandler().resolve(request).getTy= pe(); try { // set a relative URI as the href; this assumes xml:base is // set to the service document e.setHref("./"); e.setBaseUri(uriHandler.constructURIString(workspace, collName)= +"/"); e.setTitle(collName); // e.addAccepts(""); // does not have the desired effect, which is to place an // empty accept element in the document, which indicates that a // feed is read-only: http://tools.ietf.org/html/rfc5023#sectio= n-8.3.4 // workaround: use a namespaced extension to accomplish that e.addExtension(AtomServerConstants.COLLECTION_ACCEPT); boolean categoriesExist =3D atomWorkspace. getAtomCollection(collName). categoriesExist(workspace, collName); // admin can setup workspaceBeans.xml to allow // stand-alone category documents, accessible via the // href attribute. Whether this is true or not // is based on the value of the // defaultProducingInLineCategoriesServiceElement value. if (categoriesExist) { Categories categories =3D e.addCategories(); // when the target of the request is the service document, // it is up to the administrator as to whether the categori= es // are placed in-line or not. if (t =3D=3D TargetType.TYPE_SERVICE) { if (atomWorkspace.getOptions() .getDefaultProducingInLineCategoriesServiceElem= ent()) { java.util.Collection categoryList =3D atomWorkspace.getAtomCollection(collName).listC= ategories(request); for (Category category : categoryList) { categories.addCategory(category); } } } else { // when the target is a collection or the admin has sai= d // that categories are always referenced, put the URI o= f // the categories doc in the categories@href value. String chref =3D atomService.getURIHandler() .constructURIString(workspace, collName) + "/$c= ategories/"; categories.setHref(chref); } } else { e.addCategories().setFixed(false); } Element api =3D getCollectionAPI(request); if (api !=3D null) { e.addExtension(getCollectionAPI(request)); } } catch (IRISyntaxException ie) { throw new BadRequestException(ie); } return e; } private Element getCollectionAPI(RequestContext request) { Abdera abdera =3D request.getServiceContext().getAbdera(); AtomWorkspace atomWorkspace =3D this.parentAtomWorkspace; AtomService atomService =3D atomWorkspace.getParentAtomService(); URIHandler uriHandler =3D atomService.getURIHandler(); =20 String workspace =3D atomWorkspace.getName(); String collName =3D this.name; =20 Factory factory =3D AtomServer.getFactory(abdera); ExtensibleElement api =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS,"link")); api.setAttributeValue("rel","api"); api.setAttributeValue("type", "{+mediaType}"); api.setAttributeValue("href","."); api.setAttributeValue("tref", "{+categoryQuery}?{+uriQuery}"); =20 ExtensibleElement mediaType =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "mediaType")); for (String mt : this.getNegotiableMimeTypes()) { ExtensibleElement mvalue =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "value")); mvalue.setText(mt); if (mt.equalsIgnoreCase(this.defaultMediaType.getMediaType())) mvalue.setAttributeValue("default", "true"); mediaType.addExtension(mvalue); } api.addExtension(mediaType); ExtensibleElement categoryQuery =3D factory.newExtensionElement( new QName( AtomServerConstants.ATOM_NS, "categoryQuery")); categoryQuery.setAttributeValue("tref", "{+catPathSep}/{+categories= }"); ExtensibleElement catpathsep =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "catPathSep")); Element cpsvalue =3D factory.newElement(new QName(AtomServerConstan= ts.ATOM_NS,"value")); cpsvalue.setText("-"); catpathsep.addExtension(cpsvalue); categoryQuery.addExtension(catpathsep); ExtensibleElement categories =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "categories")); Element catpattern =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "pattern")); catpattern.setText("(\\([.:a-zA-Z0-9]*\\)[a-zA-Z0-9]+/|[aA][nN][dD]= /|[oO][rR]/)*"); categories.addExtension(catpattern); ExtensibleElement link =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS,"link")); link.setAttributeValue("rel","suggestions"); link.setAttributeValue("type","application/vnd.nrcan.suggestions+{s= ubtype}"); link.setAttributeValue("href", "."); link.setAttributeValue("tref", "{?q}"); link.setBaseUri("./$categories/"); ExtensibleElement cat_sugg_link_subtype =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "subtype")); cat_sugg_link_subtype.addSimpleExtension(new QName(AtomServerConsta= nts.ATOM_NS, "value"), "json"); cat_sugg_link_subtype.addSimpleExtension(new QName(AtomServerConsta= nts.ATOM_NS, "value"), "xml"); link.addExtension(cat_sugg_link_subtype); ExtensibleElement cat_sugg_link_q =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "q")); cat_sugg_link_q.addSimpleExtension(new QName(AtomServerConstants.AT= OM_NS, "pattern"), "[ \\+.:\\-a-zA-Z0-9]*"); link.addExtension(cat_sugg_link_q); categories.addExtension(link); categoryQuery.addExtension(categories); api.addExtension(categoryQuery); ExtensibleElement uriQuery =3D factory.newExtensionElement( new QName( AtomServerConstants.ATOM_NS, "uriQuery")); uriQuery.setAttributeValue("tref", "{+q}{bbox}&updated-min=3D{u= pdatedMin}&updated-max=3D{updatedMax}&max-results=3D{maxResults}&entry-type= =3D{entryType}{&callback}&sort-field=3D{sortField}{&alt}"); ExtensibleElement q =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "q")); Element qpattern =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "pattern")); qpattern.setText("[ \\+.:\\-a-zA-Z0-9]*"); q.addExtension(qpattern); ExtensibleElement q_sugg_link =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "link")); q_sugg_link.setAttributeValue("rel", "suggestions"); q_sugg_link.setAttributeValue("type", "application/vnd.nrcan.sugges= tions+{subtype}"); q_sugg_link.setAttributeValue("href", "."); q_sugg_link.setAttributeValue("tref", "{?q}"); ExtensibleElement subtype =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "subtype")); ExtensibleElement valuexml =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "value")); valuexml.setText("xml"); ExtensibleElement valuejson =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "value")); valuejson.setText("json"); subtype.addExtension(valuexml); subtype.addExtension(valuejson); q_sugg_link.addExtension(subtype); ExtensibleElement q_sugg_link_q =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "q")); q_sugg_link_q.addExtension((Element)qpattern.clone()); q_sugg_link.addExtension(q_sugg_link_q); q.addExtension(q_sugg_link); uriQuery.addExtension(q); ExtensibleElement bbox =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "bbox")); bbox.setAttributeValue("format","west,south,east,north"); bbox.setAttributeValue("units","decimal degrees"); Element bboxpattern =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "pattern")); bboxpattern.setText("-[\\d]{1,3}[\\.][\\d]{1,},-[\\d]{1,2}[\\.][\\d= ]{1,},[\\d]{1,3}[\\.][\\d]{1,},[\\d]{1,2}[\\.][\\d]{1,}"); bbox.addExtension(bboxpattern); ExtensibleElement bbox_sugg_link =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "link")); //http://geogratis.gc.ca/loc/en/loc?q=3Dfalse&match=3Dleading bbox_sugg_link.setAttributeValue("rel", "suggestions"); bbox_sugg_link.setAttributeValue("type", "application/vnd.nrcan.sug= gestions+{subtype}"); bbox_sugg_link.setAttributeValue("href", "."); bbox_sugg_link.setAttributeValue("tref", "?match=3Dleading&{q}"); bbox_sugg_link.setBaseUri("http://geogratis.gc.ca/loc/en/loc/"); bbox_sugg_link.addExtension((Element)subtype.clone()); ExtensibleElement bbox_sugg_link_q =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "q")); Element bbox_sugg_link_qpattern =3D factory.newElement( new QName(AtomServerConstants.ATOM_NS, "pattern")); bbox_sugg_link_qpattern.setText("[ \\+.:\\-a-zA-Z0-9]*"); bbox_sugg_link_q.addExtension(bbox_sugg_link_qpattern); bbox_sugg_link.addExtension(bbox_sugg_link_q); bbox.addExtension(bbox_sugg_link); String date_regex =3D "[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][= 0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30))= )(T{0,1}(([0-1][0-9])|([2][0-3])):[0-5][0-9]:([0-5][0-9])(\\.[\\d]{0,2}){0,= 1})(Z|([\\-+]([0-1][0-9]|2[0-3]))(:[0-5][0-9])?)"; uriQuery.addExtension(bbox); ExtensibleElement updated_min =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "updatedMin")); Element updated_minpattern =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "pattern")); // the regex is rough and may allow more than it should... updated_minpattern.setText(date_regex); updated_min.addExtension(updated_minpattern); uriQuery.addExtension(updated_min); ExtensibleElement updated_max =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "updatedMax")); Element updated_maxpattern =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "pattern")); updated_maxpattern.setText(date_regex); updated_max.addExtension(updated_maxpattern); uriQuery.addExtension(updated_max); ExtensibleElement max_results =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "maxResults")); Element max_resultspattern =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "pattern")); int maxfull =3D atomWorkspace.getOptions().getMaxFullMaxResults(); int maxlink =3D atomWorkspace.getOptions().getMaxLinkMaxResults(); int max =3D maxlink > maxfull ? maxlink : maxfull; // the domain of max-results depends on the value of entry-type, bu= t // for the sake of simplicity, we'll put out a regex which covers t= he // maximum possible range max_resultspattern.setText(NumericRangeRegexGenerator.rangeRegex(0,= max)); max_results.addExtension(max_resultspattern); uriQuery.addExtension(max_results); ExtensibleElement entry_type =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "entryType")); for (EntryType et : EntryType.values()) { ExtensibleElement entry_type_value =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "value")); entry_type_value.setText(et.name()); if (et =3D=3D EntryType.link) entry_type_value.setAttributeValue("default", "true"); entry_type.addExtension(entry_type_value); } uriQuery.addExtension(entry_type); ExtensibleElement callback =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "callback")); Element callbackpattern =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "pattern")); callbackpattern.setText("[a-zA-Z0-9]{1,64}"); callback.addExtension(callbackpattern); =20 uriQuery.addExtension(callback); ExtensibleElement locale =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "locale")); Element locale_en_CA =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "value")); locale_en_CA.setText("en_CA"); Element locale_fr_CA =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "value")); locale_fr_CA.setText("fr_CA"); // set the default value of locale to correspond with the en/fr // servlet mapping convention. This can be overridden by the clien= t // inserting a locale parameter. if (uriHandler.getServletMapping().equalsIgnoreCase("fr")) locale_fr_CA.setAttributeValue("default", "true"); else locale_en_CA.setAttributeValue("default", "true"); locale.addExtension(locale_en_CA); locale.addExtension(locale_fr_CA); uriQuery.addExtension(locale); ExtensibleElement sort =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "sortField")); Element sort_value =3D factory.newElement( new QName(AtomServerConstants.ATOM_NS, "value")); sort_value.setText(SortType.spatial.name()); Element default_sort_value =3D (Element)sort_value.clone(); default_sort_value.setText(SortType.edited.name()); default_sort_value.setAttributeValue("default", "true"); sort.addExtension(default_sort_value); sort.addExtension(sort_value); =20 uriQuery.addExtension(sort); // alt will have a more elaborate contents, in which the media type= and // the 'file extension' are associated. The media type is intended= as // legitimate values of the Accept: protocol header, whereas the fi= le // extension is intended to be supplied via the alt parameter to id= entify // a resource which is a view onto a single format among many possi= ble // formats negotiable from the un-parameterized resource. The head= er // takes priority over the URI parameter (? - verify before putting= this // in api documentation. ExtensibleElement alt =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "alt")); for (String ext:this.getNegotiableFormatExtensions()) { ExtensibleElement mvalue =3D factory.newExtensionElement( new QName(AtomServerConstants.ATOM_NS, "value")); mvalue.setText(ext); if (ext.equalsIgnoreCase(this.defaultMediaType.getExtension())) mvalue.setAttributeValue("default", "true"); alt.addExtension(mvalue); } uriQuery.addExtension(alt); api.addExtension(uriQuery); return api; }=