You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(48) |
Dec
(31) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(22) |
Feb
(68) |
Mar
(185) |
Apr
(11) |
May
(21) |
Jun
(23) |
Jul
(46) |
Aug
(69) |
Sep
(211) |
Oct
(26) |
Nov
(51) |
Dec
(52) |
2006 |
Jan
(13) |
Feb
(13) |
Mar
(8) |
Apr
(21) |
May
(17) |
Jun
(100) |
Jul
(34) |
Aug
(23) |
Sep
(26) |
Oct
(16) |
Nov
|
Dec
|
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(66) |
Oct
(10) |
Nov
(1) |
Dec
|
2008 |
Jan
|
Feb
|
Mar
(1) |
Apr
(3) |
May
(8) |
Jun
(5) |
Jul
(31) |
Aug
(8) |
Sep
(11) |
Oct
(6) |
Nov
|
Dec
|
2012 |
Jan
(13) |
Feb
(2) |
Mar
(9) |
Apr
(6) |
May
(24) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(120) |
2013 |
Jan
(6) |
Feb
(35) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <ap...@vh...> - 2006-09-15 11:01:03
|
Author: apevec Date: 2006-09-15 12:52:49 +0200 (Fri, 15 Sep 2006) New Revision: 1317 Modified: trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSConfig.java trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSConfig_parameter.properties trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSService.java Log: from francois.mounier: * optional XSLT processing instructions parameter Modified: trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSConfig.java =================================================================== --- trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSConfig.java 2006-09-14 10:22:20 UTC (rev 1316) +++ trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSConfig.java 2006-09-15 10:52:49 UTC (rev 1317) @@ -38,11 +38,17 @@ private static final Logger s_log = Logger.getLogger(RSSConfig.class); private final Parameter m_categoryKey; + private final Parameter m_processingInstruction_xslt; public RSSConfig() { m_categoryKey = new RSSCategoryKeyParameter ("com.arsdigita.london.rss.categoryKey", Parameter.REQUIRED, "RSS"); register(m_categoryKey); + + m_processingInstruction_xslt = new StringParameter + ("com.arsdigita.london.rss.processingInstruction_xslt", Parameter.OPTIONAL, null); + register(m_processingInstruction_xslt); + loadInfo(); } @@ -51,6 +57,10 @@ return (String) get(m_categoryKey); } + public String getPIxslt() { + return (String) get(m_processingInstruction_xslt); + } + private static class RSSCategoryKeyParameter extends StringParameter { RSSCategoryKeyParameter(final String name, Modified: trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSConfig_parameter.properties =================================================================== --- trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSConfig_parameter.properties 2006-09-14 10:22:20 UTC (rev 1316) +++ trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSConfig_parameter.properties 2006-09-15 10:52:49 UTC (rev 1317) @@ -2,3 +2,7 @@ com.arsdigita.london.rss.categoryKey.purpose=The category purpose key defining RSS channels com.arsdigita.london.rss.categoryKey.format=[string] com.arsdigita.london.rss.categoryKey.example=RSS +com.arsdigita.london.rss.processingInstruction_xslt.title=The frontend path to xslt stylesheet +com.arsdigita.london.rss.processingInstruction_xslt.purpose= Path for browser local xslt styling of public RSS feeds +com.arsdigita.london.rss.processingInstruction_xslt.format=[string] +com.arsdigita.london.rss.processingInstruction_xslt.example=/ccm-ldn-theme/__ccm__/themes-prod/theme-name/rss-feed.xsl Modified: trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSService.java =================================================================== --- trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSService.java 2006-09-14 10:22:20 UTC (rev 1316) +++ trunk/ccm-ldn-rss/src/com/arsdigita/london/rss/RSSService.java 2006-09-15 10:52:49 UTC (rev 1317) @@ -48,6 +48,7 @@ import org.jdom.Element; import org.jdom.Namespace; import org.jdom.output.XMLOutputter; +import org.jdom.ProcessingInstruction; import com.arsdigita.kernel.User; /** * Methods for generating RSS Channels & Items. @@ -64,6 +65,16 @@ public class RSSService { private static org.apache.log4j.Logger s_log = org.apache.log4j.Logger.getLogger(RSSService.class); + + private static final RSSConfig s_config = new RSSConfig(); + + static { + s_config.load(); + } + + public static RSSConfig getConfig() { + return s_config; + } /** * Generates an RSS channel for a specified category and and all of its Articles. @@ -297,8 +308,13 @@ } // Write XML to the output stream - Document doc = new Document(rdf); + Document doc = new Document(); + if (getConfig().getPIxslt()!= null) { + doc.addContent(new ProcessingInstruction("xml-stylesheet","type=\"text/xsl\" href=\"" + getConfig().getPIxslt() + "\"")); + } + doc.setRootElement(rdf); + response.setContentType("text/xml; charset=UTF-8"); XMLOutputter xmlOutput = new XMLOutputter("UTF-8"); |
From: <ss...@vh...> - 2006-09-14 10:30:32
|
Author: sshinde Date: 2006-09-14 12:22:20 +0200 (Thu, 14 Sep 2006) New Revision: 1316 Modified: contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/Wordxml.java contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlFileProcessor.java contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlImage.java contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlResources.java Log: Forgot to checkin these files. Modified: contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/Wordxml.java =================================================================== --- contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/Wordxml.java 2006-09-07 08:47:15 UTC (rev 1315) +++ contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/Wordxml.java 2006-09-14 10:22:20 UTC (rev 1316) @@ -30,6 +30,7 @@ import com.arsdigita.cms.ContentPage; import com.arsdigita.cms.ImageAssetCollection; import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.domain.DomainCollection; import com.arsdigita.persistence.DataAssociation; import com.arsdigita.persistence.DataObject; import com.arsdigita.persistence.OID; @@ -134,7 +135,7 @@ } /** - * Add the content of the file to specified field. + * Add the content of the file to specified field. Useful for debugging purposes. */ // public void addFileContent(String fieldName, File file) // throws FileNotFoundException, IOException { @@ -169,11 +170,38 @@ return null; } } + + /** + * Return a Single Image filtered by it's name. + */ + public WordxmlImage getSingleImage (String imageName) { + + DataAssociation assoc = (DataAssociation) get(DOC_IMAGES); + + if (assoc == null) { + return null; + } + + DomainCollection dColl = new DomainCollection(assoc); + dColl.addEqualsFilter(WordxmlImage.NAME , imageName); + WordxmlImage retImg = null; + if (dColl != null) { + if (dColl.next()) { + retImg = (WordxmlImage) dColl.getDomainObject(); + } + } + return retImg; + } + /** + * Utility function to delete all images associated with the item. + */ public void deleteAllImages() { ImageAssetCollection coll = getImages(); - while (coll.next()) { - coll.getImage().delete(); + if (null != coll) { + while (coll.next()) { + coll.getImage().delete(); + } } } Modified: contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlFileProcessor.java =================================================================== --- contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlFileProcessor.java 2006-09-07 08:47:15 UTC (rev 1315) +++ contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlFileProcessor.java 2006-09-14 10:22:20 UTC (rev 1316) @@ -110,12 +110,21 @@ File docbookFile = transformToDocbook(); // Add docbook xml content to item. writeFileToDB(Wordxml.DOCBOOKXML, docbookFile); - + //File qaDocFile = transformToQADoc(docbookFile); + File htmlFile = new File(wxmlResources.getHTMLOutputFile()); + writeHtmlFile(docbookFile, htmlFile); + // Finally cleanup the files only if debugging is not enabled. if (! s_log.isDebugEnabled()) { cleanup(); } } + /** + * Reads the uploaded XML Document file and transforms it into a Doc book XML. + * This is a two step process. First one is to convert it into an intermediate + * format called achieved by word2styels xsl template. Second step to is to + * convert this intermediate format into Doc book format. + */ private File transformToDocbook() throws Exception { /* * Step One is to transform uploaded wordxml file into intermediate @@ -134,8 +143,8 @@ s_log .debug("DTD Location Setting: " + WordxmlResources.getDtdLoc()); - s_log.debug("Actual DTD Location: " - + transformer.getParameter("doctype-system-id").toString()); +// s_log.debug("Actual DTD Location: " +// + transformer.getParameter("doctype-system-id").toString()); } // Specify the location where Base64 encoded images will be written // by xsl files @@ -146,12 +155,12 @@ transformer.transform(new StreamSource(sourceFile), result); /* - * Decode and add images which are emitted by word2styles phase. + * Decode and add images to the database which are emitted by word2styles phase. */ decodeAndAddImages(); /* - * Step two is apply addtional stylesheets and convert it into docbook + * Step two is to apply addtional stylesheets and convert it into docbook * format */ factory = TransformerFactory.newInstance(); @@ -159,10 +168,9 @@ temps = factory.newTemplates(new StreamSource(new File(styles))); transformer = temps.newTransformer(); - transformer.setParameter("image-input-loc", wxmlResources - .getDecodedImagesDir()); - s_log.debug("Image Input Location is: " - + transformer.getParameter("image-input-loc")); + //Put the URL of our JSP which will serve out images for us. + transformer.setParameter("image-input-loc", wxmlResources.getImageJSP()); + s_log.debug("Image Input Location is: " + wxmlResources.getImageJSP()); DOMSource domSrc = new DOMSource(result.getNode()); File docBookFile = new File(wxmlResources.getDocbookOutputFile()); @@ -170,6 +178,40 @@ return docBookFile; } + private void transformToQADoc (File docBookFile) throws Exception { + TransformerFactory factory = TransformerFactory.newInstance(); + String styles = WordxmlResources.getQADocTemplate(); + Templates temps = factory.newTemplates(new StreamSource( + new File(styles))); + + Transformer transformer = temps.newTransformer(); + transformer.setParameter("image-input-loc", wxmlResources + .getDecodedImagesDir()); + s_log.debug("Image Input Location is: " + + transformer.getParameter("image-input-loc")); + // Step One + DOMResult result = new DOMResult(); + transformer.transform(new StreamSource(docBookFile), result); + + // Step Two + styles = WordxmlResources.getQAErrorTemplate(); + temps = factory.newTemplates(new StreamSource(new File(styles))); + transformer = temps.newTransformer(); + transformer.setParameter("image-input-loc", wxmlResources + .getDecodedImagesDir()); + DOMSource src = new DOMSource(result.getNode()); + result = new DOMResult(); + transformer.transform(src, (result)); + Document doc = (Document) result.getNode(); + // Step 3 + temps = factory.newTemplates(new DOMSource(doc)); + transformer = temps.newTransformer(); + transformer.setParameter("image-input-loc", wxmlResources + .getDecodedImagesDir()); + result = new DOMResult(); + transformer.transform(new StreamSource(sourceFile), result); + } + // TODO: This is a little in efficient. private void writeFileToDB(String fieldName, File file) throws FileNotFoundException, IOException { @@ -231,72 +273,50 @@ } /** - * Transform the uploaded WordXML file to intermediate format. Returns a - * File handle containing the transformed document. I have choosen to write - * it to file instead in memory processing bcoz it's easy to debug and - * understand the issues. - * - */ - // private File convertWord2Styles() throws Exception { - // File outputFile = null; - // TransformerFactory factory = TransformerFactory.newInstance(); - // String styles = WordxmlResources.getWord2stylesTemplate(); - // Templates temps = factory.newTemplates(new StreamSource( - // new File(styles))); - // Transformer transformer = temps.newTransformer(); - // // Specify the location of the DTD - // transformer.setParameter("doctype-system-id", WordxmlResources - // .getDtdLoc()); - // s_log.debug("Dtd Location is: " - // + transformer.getParameter("doctype-system-id").hashCode()); - // // Specify the location where Base64 encoded images will be written - // // by xsl files - // transformer.setParameter("image-output-loc", wxmlResources - // .getEncodedImagesDir()); - // - // outputFile = new File(wxmlResources.getWord2StylesOutputFile()); - // transformer.transform(new StreamSource(sourceFile), new StreamResult( - // outputFile)); - // return outputFile; - // } - /** * Reads source docbook file , applies transformation and writes outputFile. * outputFile is the html file. * * @param docbookFile * @param outputFile */ - // private void writeHtmlFile(File docbookFile, File outputFile) - // throws Exception { - // TransformerFactory factory = TransformerFactory.newInstance(); - // String styles = WordxmlResources.getDocbook2HtmlTemplate(); - // Templates temps = factory.newTemplates(new StreamSource( - // new File(styles))); - // - // Transformer transformer = temps.newTransformer(); - // transformer.transform(new StreamSource(docbookFile), new StreamResult( - // outputFile)); - // } - // private File convertToDocbook(File phaseOneFile) throws Exception { - // TransformerFactory factory = TransformerFactory.newInstance(); - // File docbookFile = new File(wxmlResources.getDocbookOutputFile()); - // String styles = WordxmlResources.getStyles2DocbookTemplate(); - // Templates temps = factory.newTemplates(new StreamSource( - // new File(styles))); - // - // Transformer transformer = temps.newTransformer(); - // transformer.setParameter("image-input-loc", wxmlResources - // .getDecodedImagesDir()); - // s_log.debug("Image Input Location is: " - // + transformer.getParameter("image-input-loc")); - // String mime = temps.getOutputProperties().getProperty( - // OutputKeys.MEDIA_TYPE); - // s_log.debug("Output Media Type is: " + mime); - // - // transformer.transform(new StreamSource(phaseOneFile), new StreamResult( - // docbookFile)); - // return docbookFile; - // } + private void writeHtmlFile(File docbookFile, File outputFile) + throws Exception { + TransformerFactory factory = TransformerFactory.newInstance(); + String styles = WordxmlResources.getDocbook2HtmlTemplate(); + Templates temps = factory.newTemplates(new StreamSource( + new File(styles))); + + if (s_log.isDebugEnabled()) { + s_log.debug("Using Templates: " + styles); + s_log.debug("Writing out HTML File to: " + outputFile.getAbsolutePath()); + } + + Transformer transformer = temps.newTransformer(); + transformer.transform(new StreamSource(docbookFile), new StreamResult( + outputFile)); + } + + private File convertToDocbook(File phaseOneFile) throws Exception { + TransformerFactory factory = TransformerFactory.newInstance(); + File docbookFile = new File(wxmlResources.getDocbookOutputFile()); + String styles = WordxmlResources.getStyles2DocbookTemplate(); + Templates temps = factory.newTemplates(new StreamSource( + new File(styles))); + + Transformer transformer = temps.newTransformer(); + transformer.setParameter("image-input-loc", wxmlResources + .getDecodedImagesDir()); + s_log.debug("Image Input Location is: " + + transformer.getParameter("image-input-loc")); + String mime = temps.getOutputProperties().getProperty( + OutputKeys.MEDIA_TYPE); + s_log.debug("Output Media Type is: " + mime); + + transformer.transform(new StreamSource(phaseOneFile), new StreamResult( + docbookFile)); + return docbookFile; + } + /** * Decode Base64 encoded images and add it to the Wordxml item. Decoding is * done by reading the image files from /tmp/wordxml/$DOCUMENT_ID/ Modified: contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlImage.java =================================================================== --- contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlImage.java 2006-09-07 08:47:15 UTC (rev 1315) +++ contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlImage.java 2006-09-14 10:22:20 UTC (rev 1316) @@ -94,6 +94,13 @@ super.setContent(content); } + /** + * Expose the super class method so that image content can be directly served. + */ + public byte[] getContent() { + return (byte[]) get(CONTENT); + } + public void setWordxmlItem (Wordxml item) { set(WORDXML_ITEM , item); } Modified: contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlResources.java =================================================================== --- contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlResources.java 2006-09-07 08:47:15 UTC (rev 1315) +++ contrib/ccm-ldn-camden-wordxml/trunk/src/com/arsdigita/camden/cms/contenttypes/WordxmlResources.java 2006-09-14 10:22:20 UTC (rev 1316) @@ -48,6 +48,8 @@ private static String DOWNLOAD_JSP = "wordxml/download.jsp"; + private static String IMAGES_JSP ="/ccm/content/admin/wordxml/serveimage.jsp"; + private String documentID = null; public WordxmlResources(String documentID) { @@ -66,6 +68,11 @@ public String getDecodedImagesDir() { return TMP_LOC + getDocumentID() + DECODED_IMAGES; } + + /** A JSP Page for now to serve out the images */ + public String getImageJSP () { + return IMAGES_JSP + "?itemID=" + getDocumentID() + "&imgName="; + } public String getTempDocumentRoot () { return TMP_LOC + getDocumentID(); @@ -87,6 +94,10 @@ return XSL_ROOT_LOC + "/xsl/styles2docbook/styles2docbook.xsl"; } + public static String getDocbook2HtmlTemplate () { + return XSL_ROOT_LOC + "/xsl/docbook-xsl-1.69.1/html/chunk.xsl"; + } + public static String getQADocTemplate() { return XSL_ROOT_LOC + "/xsl/qa/wordqa.xsl"; } @@ -103,6 +114,10 @@ return getOutputLoc() + "/docbook.xml"; } + public String getHTMLOutputFile() { + return getOutputLoc() + "htmlfile.html"; + } + public static String getDtdLoc() { return XSL_ROOT_LOC + "/dtd/camden.dtd"; } |
From: <ssk...@vh...> - 2006-09-07 08:55:03
|
Author: sskracic Date: 2006-09-07 10:47:15 +0200 (Thu, 07 Sep 2006) New Revision: 1315 Modified: trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl trunk/ccm-cms/src/com/arsdigita/cms/Folder.java trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java Log: Another performance improvement for Folder browser: instead of submitting a query for each visible folder only to check whether it has children (to determine the 'Delete' link visibility), retrieve this attribute together with all others in Folder.ItemCollection. Modified: trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl =================================================================== --- trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl 2006-09-07 08:18:08 UTC (rev 1314) +++ trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl 2006-09-07 08:47:15 UTC (rev 1315) @@ -114,6 +114,7 @@ ContentItem item; Boolean isFolder; Boolean hasLiveVersion; + Boolean hasChildren; do { select @@ -124,7 +125,11 @@ from cms_items where master_id = i.item_id) then 1 else 0 end as has_live_version, - case when 0 = nvl(f.folder_id, 0) then 0 else 1 end as is_folder + case when 0 = nvl(f.folder_id, 0) then 0 else 1 end as is_folder, + case when exists (select 1 + from cms_items i2 + where i2.parent_id = i.item_id) + then 1 else 0 end as has_children from cms_items i, acs_objects a, @@ -157,6 +162,7 @@ item.type.label = label; isFolder = is_folder; hasLiveVersion = has_live_version; + hasChildren = has_children; } } @@ -172,6 +178,7 @@ ContentItem item; Boolean isFolder; Boolean hasLiveVersion; + Boolean hasChildren; BigDecimal bundleID; do { @@ -184,6 +191,10 @@ from cms_items where master_id = i.item_id) then 1 else 0 end as has_live_version, + case when exists (select 1 + from cms_items i2 + where i2.parent_id = i.item_id) + then 1 else 0 end as has_children, 0 as type_id, '' as label, 0 as bundle_id from @@ -211,6 +222,10 @@ from cms_items where master_id = i.item_id) then 1 else 0 end as has_live_version, + case when exists (select 1 + from cms_items i2 + where i2.parent_id = i.item_id) + then 1 else 0 end as has_children, t.type_id as type_id, t.label as label, b.bundle_id as bundle_id from @@ -254,5 +269,6 @@ item.auditing.creationIP = aud.creation_ip; isFolder = is_folder; hasLiveVersion = has_live_version; + hasChildren = has_children; } } Modified: trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl =================================================================== --- trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl 2006-09-07 08:18:08 UTC (rev 1314) +++ trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl 2006-09-07 08:47:15 UTC (rev 1315) @@ -82,6 +82,7 @@ ContentItem item; Boolean isFolder; Boolean hasLiveVersion; + Boolean hasChildren; do { select @@ -96,7 +97,11 @@ case when exists (select 1 from cms_folders f where i.item_id = f.folder_id) - then 1 else 0 end as is_folder + then 1 else 0 end as is_folder, + case when exists (select 1 + from cms_items i2 + where i2.parent_id = i.item_id) + then 1 else 0 end as has_children from acs_objects a, cms_items i @@ -124,6 +129,7 @@ item.type.label = label; isFolder = is_folder; hasLiveVersion = has_live_version; + hasChildren = has_children; } } @@ -137,6 +143,7 @@ ContentItem item; Boolean isFolder; Boolean hasLiveVersion; + Boolean hasChildren; BigDecimal bundleID; do { @@ -149,6 +156,10 @@ from cms_items where master_id = i.item_id) then 1 else 0 end as has_live_version, + case when exists (select 1 + from cms_items i2 + where i2.parent_id = i.item_id) + then 1 else 0 end as has_children, 0 as type_id, '' as label, 0 as bundle_id from @@ -176,6 +187,10 @@ from cms_items where master_id = i.item_id) then 1 else 0 end as has_live_version, + case when exists (select 1 + from cms_items i2 + where i2.parent_id = i.item_id) + then 1 else 0 end as has_children, t.type_id as type_id, t.label as label, b.bundle_id as bundle_id from @@ -219,5 +234,6 @@ item.auditing.creationIP = aud.creation_ip; isFolder = is_folder; hasLiveVersion = has_live_version; + hasChildren = has_children; } } Modified: trunk/ccm-cms/src/com/arsdigita/cms/Folder.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/Folder.java 2006-09-07 08:18:08 UTC (rev 1314) +++ trunk/ccm-cms/src/com/arsdigita/cms/Folder.java 2006-09-07 08:47:15 UTC (rev 1315) @@ -286,7 +286,7 @@ */ public ContentItem getItem(final String name, final boolean isFolder) { - + DataQuery query; if (isFolder) { query = SessionManager.getSession().retrieveQuery(FOLDER_QUERY); @@ -385,7 +385,7 @@ } public ContentItem publish(final LifecycleDefinition cycleDef, - final Date startDate) { + final Date startDate) { if (s_log.isInfoEnabled()) { s_log.info("Publishing folder " + this); } @@ -559,10 +559,10 @@ * property */ public boolean copyProperty(final CustomCopy srcItem, - final Property property, - final ItemCopier copier) { + final Property property, + final ItemCopier copier) { // Ignore the items association. - String attrName = property.getName(); + String attrName = property.getName(); if (ITEMS.equals(attrName) || INDEX.equals(attrName)) { return true; } @@ -584,6 +584,7 @@ public static class ItemCollection extends com.arsdigita.cms.ItemCollection { private final static String IS_FOLDER = "isFolder"; + private final static String HAS_CHILDREN = "hasChildren"; private final static String ITEM = "item"; private final static String HAS_LIVE_VERSION = "hasLiveVersion"; private final static String TYPE_LABEL = "type.label"; @@ -593,7 +594,7 @@ /** - * Constructor + * Constructor * @param query the Data Query to use to retrieve the collection * @param bSort whether to sort the collection by isFolder and ID */ @@ -602,7 +603,7 @@ //one constructor. But, that would break the existing API public ItemCollection(DataQuery query, boolean bSort) { super(new DataQueryDataCollectionAdapter(doAlias(query), ITEM)); - + init(query, bSort); } @@ -618,14 +619,14 @@ } private void init(DataQuery query, boolean bSort) { - m_query = query; + m_query = query; if (bSort) { m_query.addOrder("isFolder desc"); - + addOrder("id desc"); - } - } + } + } private static DataQuery doAlias(final DataQuery query) { query.alias("isFolder", "isFolder"); @@ -648,13 +649,13 @@ public String getDisplayName() { return (String) get(DISPLAY_NAME); } - + /** * For performance reaons, override superclass methods and * try to get the audit info without instantiating a content item. - * We know this can help because the getPrimaryInstances + * We know this can help because the getPrimaryInstances * query retrieves the audit info directly - */ + */ public Date getCreationDate() { DataObject dobj = (DataObject) get(AUDIT_TRAIL); if (dobj != null){ @@ -664,7 +665,7 @@ return super.getCreationDate(); } } - + public Date getLastModifiedDate() { DataObject dobj = (DataObject) get(AUDIT_TRAIL); if (dobj != null){ @@ -673,7 +674,7 @@ } else { return super.getLastModifiedDate(); } - } + } /** * Return the pretty name of the content type of the current item. If @@ -714,6 +715,11 @@ return result.booleanValue(); } + public boolean hasChildren() { + Boolean result = (Boolean) m_query.get(HAS_CHILDREN); + return result.booleanValue(); + } + public boolean isLive() { String version = (String) get(ContentItem.VERSION); if (ContentItem.LIVE.equals(version) ) { @@ -750,9 +756,9 @@ } public static void setUserHomeFolder(User user,Folder folder) { - UserHomeFolderMap map = UserHomeFolderMap.findOrCreateUserHomeFolderMap(user,folder.getContentSection()); - map.setHomeFolder(folder); - map.save(); + UserHomeFolderMap map = UserHomeFolderMap.findOrCreateUserHomeFolderMap(user,folder.getContentSection()); + map.setHomeFolder(folder); + map.save(); } public static Folder getUserHomeFolder(User user,ContentSection section) { @@ -765,7 +771,7 @@ SecurityManager sm; if (context.hasSecurityManager()) { sm = CMS.getContext().getSecurityManager(); - } else { + } else { sm = new SecurityManager(section); } if ( !sm.canAccess(user,SecurityConstants.PREVIEW_PAGES,folder) ) { Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java 2006-09-07 08:18:08 UTC (rev 1314) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java 2006-09-07 08:47:15 UTC (rev 1315) @@ -593,25 +593,31 @@ } if (m_itemColl.isLive()) { - s_log.debug("The item is live; it cannot be deleted"); + if (s_log.isDebugEnabled()) { + s_log.debug("The item is live; it cannot be deleted"); + } return false; } if (m_itemColl.isFolder()) { - if (((Folder) m_itemColl.getContentItem()).isEmpty()) { - s_log.debug("The item is an empty folder; it may be " + - "deleted"); - + if (m_itemColl.hasChildren()) { + if (s_log.isDebugEnabled()) { + s_log.debug("The item is an empty folder; it may be " + + "deleted"); + } return true; } else { - s_log.debug("The folder is not empty; it cannot be " + - "deleted"); - + if (s_log.isDebugEnabled()) { + s_log.debug("The folder is not empty; it cannot be " + + "deleted"); + } return false; } } else { - s_log.debug("The item is not a folder; it may be deleted"); + if (s_log.isDebugEnabled()) { + s_log.debug("The item is not a folder; it may be deleted"); + } return true; } |
From: <ap...@vh...> - 2006-09-07 08:25:56
|
Author: apevec Date: 2006-09-07 10:18:08 +0200 (Thu, 07 Sep 2006) New Revision: 1314 Added: trunk/ccm-core/etc/src/ trunk/ccm-core/etc/src/commons-cli-1.0.src.zip trunk/ccm-core/lib/commons-cli-1.0.jar Removed: trunk/ccm-core/lib/commons-cli-1.0-beta-2-dev.jar Modified: trunk/ccm-core/etc/java-libs.txt Log: Commons CLI JAR update Modified: trunk/ccm-core/etc/java-libs.txt =================================================================== --- trunk/ccm-core/etc/java-libs.txt 2006-09-07 08:09:21 UTC (rev 1313) +++ trunk/ccm-core/etc/java-libs.txt 2006-09-07 08:18:08 UTC (rev 1314) @@ -4,13 +4,14 @@ aspectjrt-1.0.5.jar 1.0.5 CPL 1.0 http://www.eclipse.org/legal/cpl-v10.html cactus-1.4.1.jar 1.4.1 APACHE http://www.apache.org/LICENSE.txt commons-beanutils.jar 1.6.1 APACHE http://www.apache.org/LICENSE.txt -commons-cli-1.0-beta-2-dev.jar 1.0 APACHE http://www.apache.org/LICENSE.txt +commons-cli-1.0.jar 1.0 APACHE http://www.apache.org/LICENSE.txt commons-codec-1.3.jar 1.3 APACHE http://www.apache.org/LICENSE.txt commons-collections-3.0.jar APACHE http://www.apache.org/LICENSE.txt commons-httpclient-2.0alpha1-20020606.jar APACHE http://www.apache.org/LICENSE.txt commons-logging-1.0.jar APACHE http://www.apache.org/LICENSE.txt commons-primitives-1.0.jar APACHE http://www.apache.org/LICENSE.txt +FCKeditor 2.2 LGPL http://www.fckeditor.net/license/ htmlarea 3.0-b BSD http://www.interactivetools.com/products/htmlarea/license.html i18n.jar 1.0 APACHE http://www.apache.org/LICENSE.txt iDoclet.jar 1.0 GPL http://www.gnu.org/copyleft/gpl.html Added: trunk/ccm-core/etc/src/commons-cli-1.0.src.zip =================================================================== (Binary files differ) Property changes on: trunk/ccm-core/etc/src/commons-cli-1.0.src.zip ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Deleted: trunk/ccm-core/lib/commons-cli-1.0-beta-2-dev.jar Added: trunk/ccm-core/lib/commons-cli-1.0.jar =================================================================== (Binary files differ) Property changes on: trunk/ccm-core/lib/commons-cli-1.0.jar ___________________________________________________________________ Name: svn:mime-type + application/octet-stream |
From: <ssk...@vh...> - 2006-09-07 08:17:12
|
Author: sskracic Date: 2006-09-07 10:09:21 +0200 (Thu, 07 Sep 2006) New Revision: 1313 Modified: trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl trunk/ccm-cms/src/com/arsdigita/cms/Folder.java trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java Log: Another substantial performance improvement for Folder Browser. For each folder visible in left folder panel, 2 additional queries are executed. This patch eliminates one of them. Modified: trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl =================================================================== --- trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl 2006-09-06 15:47:44 UTC (rev 1312) +++ trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl 2006-09-07 08:09:21 UTC (rev 1313) @@ -173,7 +173,6 @@ Boolean isFolder; Boolean hasLiveVersion; BigDecimal bundleID; - BasicAuditTrail auditTrail; do { select @@ -248,11 +247,11 @@ item.name = i.name; item.type.id = type_id; item.type.label = label; - auditTrail.id = i.item_id; - auditTrail.lastModifiedIP = aud.modifying_ip; - auditTrail.lastModifiedDate = aud.last_modified; - auditTrail.creationDate = aud.creation_date; - auditTrail.creationIP = aud.creation_ip; + item.auditing.id = i.item_id; + item.auditing.lastModifiedIP = aud.modifying_ip; + item.auditing.lastModifiedDate = aud.last_modified; + item.auditing.creationDate = aud.creation_date; + item.auditing.creationIP = aud.creation_ip; isFolder = is_folder; hasLiveVersion = has_live_version; } Modified: trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl =================================================================== --- trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl 2006-09-06 15:47:44 UTC (rev 1312) +++ trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl 2006-09-07 08:09:21 UTC (rev 1313) @@ -138,7 +138,6 @@ Boolean isFolder; Boolean hasLiveVersion; BigDecimal bundleID; - BasicAuditTrail auditTrail; do { select @@ -213,11 +212,11 @@ item.name = i.name; item.type.id = type_id; item.type.label = label; - auditTrail.id = i.item_id; - auditTrail.lastModifiedIP = aud.modifying_ip; - auditTrail.lastModifiedDate = aud.last_modified; - auditTrail.creationDate = aud.creation_date; - auditTrail.creationIP = aud.creation_ip; + item.auditing.id = i.item_id; + item.auditing.lastModifiedIP = aud.modifying_ip; + item.auditing.lastModifiedDate = aud.last_modified; + item.auditing.creationDate = aud.creation_date; + item.auditing.creationIP = aud.creation_ip; isFolder = is_folder; hasLiveVersion = has_live_version; } Modified: trunk/ccm-cms/src/com/arsdigita/cms/Folder.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/Folder.java 2006-09-06 15:47:44 UTC (rev 1312) +++ trunk/ccm-cms/src/com/arsdigita/cms/Folder.java 2006-09-07 08:09:21 UTC (rev 1313) @@ -587,7 +587,7 @@ private final static String ITEM = "item"; private final static String HAS_LIVE_VERSION = "hasLiveVersion"; private final static String TYPE_LABEL = "type.label"; - private final static String AUDIT_TRAIL="auditTrail"; + private final static String AUDIT_TRAIL="item.auditing"; private DataQuery m_query; Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java 2006-09-06 15:47:44 UTC (rev 1312) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java 2006-09-07 08:09:21 UTC (rev 1313) @@ -296,10 +296,10 @@ itemColl.setOrder("lower(item." + ContentItem.NAME + ") " + direction); } else if ( sortKey.equals(SORT_KEY_LAST_MODIFIED_DATE)) { - itemColl.setOrder("lower(auditTrail.lastModifiedDate) " + + itemColl.setOrder("lower(item.auditing.lastModifiedDate) " + direction); } else if ( sortKey.equals(SORT_KEY_CREATION_DATE)) { - itemColl.setOrder("lower(auditTrail.creationDate) " + + itemColl.setOrder("lower(item.auditing.creationDate) " + direction); } |
From: <ap...@vh...> - 2006-09-06 15:55:33
|
Author: apevec Date: 2006-09-06 17:47:44 +0200 (Wed, 06 Sep 2006) New Revision: 1312 Modified: trunk/ccm-core/src/com/arsdigita/bebop/page/PageTransformer.java Log: >From qu...@ba... used by Mandalay theme Modified: trunk/ccm-core/src/com/arsdigita/bebop/page/PageTransformer.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/bebop/page/PageTransformer.java 2006-09-06 12:40:30 UTC (rev 1311) +++ trunk/ccm-core/src/com/arsdigita/bebop/page/PageTransformer.java 2006-09-06 15:47:44 UTC (rev 1312) @@ -160,6 +160,13 @@ } }); + registerXSLParameterGenerator + ("user-agent", + new XSLParameterGenerator() { + public String generateValue(HttpServletRequest request) { + return request.getHeader("User-Agent"); + } + }); } // XXX These need to move somewhere else. |
From: <ssk...@vh...> - 2006-09-06 12:48:19
|
Author: sskracic Date: 2006-09-06 14:40:30 +0200 (Wed, 06 Sep 2006) New Revision: 1311 Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java Log: Why, why, oh why we need to traverse *each* folder in content section folder tree if a node is marked as collapsed? So, regardless of the collapsed/expanded state, the FolderBrowser generated at least 2 queries per *each folder in a content section* on *each request*. Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java 2006-09-04 11:26:55 UTC (rev 1310) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java 2006-09-06 12:40:30 UTC (rev 1311) @@ -41,6 +41,7 @@ import com.arsdigita.persistence.DataQuery; import com.arsdigita.util.LockableImpl; import java.math.BigDecimal; +import java.util.Collections; import java.util.Iterator; import org.apache.log4j.Logger; @@ -74,12 +75,16 @@ * @return a tree model that lists the hierarchy of folders underneath the * folder returnedby {@link #getRoot getRoot}. */ - public com.arsdigita.bebop.tree.TreeModel makeModel(Tree t, PageState s) { + public com.arsdigita.bebop.tree.TreeModel makeModel(final Tree t, PageState s) { return new DataQueryTreeModel(getRoot(s).getID(), "com.arsdigita.cms.getRootFolder", "com.arsdigita.cms.getSubFolders") { public Iterator getChildren(TreeNode node, PageState data) { + String nodeKey = node.getKey().toString(); + if (t.isCollapsed(nodeKey, data)) { + return Collections.EMPTY_LIST.iterator(); + } Party party = Kernel.getContext().getParty(); OID partyOID = null; if (party == null) { |
From: <ssk...@vh...> - 2006-09-04 11:34:33
|
Author: sskracic Date: 2006-09-04 13:26:55 +0200 (Mon, 04 Sep 2006) New Revision: 1310 Modified: trunk/ccm-cms/src/com/arsdigita/cms/dispatcher/CMSPage.java Log: Implemented permission check on item level in admin pages, ie. even if someone is performing URL surgery to get to the item he's not supposed to see, he'll be greeted with AccessDeniedException. Modified: trunk/ccm-cms/src/com/arsdigita/cms/dispatcher/CMSPage.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/dispatcher/CMSPage.java 2006-09-04 10:30:53 UTC (rev 1309) +++ trunk/ccm-cms/src/com/arsdigita/cms/dispatcher/CMSPage.java 2006-09-04 11:26:55 UTC (rev 1310) @@ -31,8 +31,11 @@ import com.arsdigita.dispatcher.RequestContext; import com.arsdigita.domain.DataObjectNotFoundException; import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.kernel.Kernel; import com.arsdigita.kernel.KernelHelper; import com.arsdigita.kernel.User; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; import com.arsdigita.persistence.OID; import com.arsdigita.sitenode.BasePresentationManager; import com.arsdigita.templating.PresentationManager; @@ -272,10 +275,20 @@ if (itemID != null) { try { - setContentItem - ((ContentItem) DomainObjectFactory.newInstance + ContentItem item = + (ContentItem) DomainObjectFactory.newInstance (new OID(ContentItem.BASE_DATA_OBJECT_TYPE, - new BigDecimal(itemID)))); + new BigDecimal(itemID))); + setContentItem(item); + PermissionDescriptor perm = new PermissionDescriptor( + SecurityManager.CMS_PREVIEW_ITEM_DESCRIPTOR, + item, + Kernel.getContext().getParty() ); + if (!PermissionService.checkPermission(perm)) { + s_log.warn("No perm to CMS_PREVIEW_ITEM " + itemID); + throw new AccessDeniedException( + "You do not have privileges to administer item " + itemID); + } } catch (DataObjectNotFoundException donfe) { s_log.warn("Failed to load content item " + itemID); } |
From: <ssk...@vh...> - 2006-09-04 10:38:31
|
Author: sskracic Date: 2006-09-04 12:30:53 +0200 (Mon, 04 Sep 2006) New Revision: 1309 Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java Log: Killing PrivilegeDescriptor.constructPrivilegeClause() since the privilege bitmap is already denormalised prior to inserting into dnm_permissions table. Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java 2006-09-04 10:28:53 UTC (rev 1308) +++ trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java 2006-09-04 10:30:53 UTC (rev 1309) @@ -531,7 +531,7 @@ Filter f = factory.simple( " exists ( com.arsdigita.kernel.permissions.PartyPermissionFilterQuery" + " and RAW[dogc.pd_object_id] = " + propertyName - + " and RAW[" + privilege.constructPrivilegeClause(null) + "] )"); + + " and RAW[" + privilege.getColumnName() + "] = 1)"); f.set("partyID", constructAccessList(partyOID));//partyOID.get("id")); return f; } @@ -547,7 +547,7 @@ Filter f = factory.simple( " exists ( com.arsdigita.kernel.permissions.ObjectPermissionFilterQuery" + " and RAW[dgm.pd_member_id] = " + propertyName - + " and RAW[" + privilege.constructPrivilegeClause(null) + "] )"); + + " and RAW[" + privilege.getColumnName() + "] = 1)"); f.set("objectID", objectOID.get("id")); return f; } Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java 2006-09-04 10:28:53 UTC (rev 1308) +++ trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java 2006-09-04 10:30:53 UTC (rev 1309) @@ -29,7 +29,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; /** @@ -343,33 +342,4 @@ } - /** - * Constructs a SQL clause ready to test for this privilege against - * the denormalised permission table where each privilege is represented - * with its own column. All column tests are ORed together. - * - * @param alias optional alias for dnm_permissions table, if null then - * no alias will be prepended to column names - * @return SQL string that should be fed directly to database - */ - public String constructPrivilegeClause(String alias) { - Iterator it = getImplyingPrivilegeNames().iterator(); - StringBuffer sql = null; - while (it.hasNext()) { - if (sql == null) { - sql = new StringBuffer(100); - sql.append("("); - } else { - sql.append(" or "); - } - PrivilegeDescriptor implyingPriv = PrivilegeDescriptor.get( (String) it.next()); - if (alias != null) { - sql.append(alias + "."); - } - sql.append(implyingPriv.getColumnName() + " = 1"); - } - sql.append(")"); - return sql.toString(); - } - } |
From: <ssk...@vh...> - 2006-09-04 10:36:33
|
Author: sskracic Date: 2006-09-04 12:28:53 +0200 (Mon, 04 Sep 2006) New Revision: 1308 Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java Log: I was wrong ... thanks to Aram, no need to check multiple columns since privilege info is already denormalised before inserting into dnm_permissions table. Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java 2006-09-01 11:27:09 UTC (rev 1307) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java 2006-09-04 10:28:53 UTC (rev 1308) @@ -152,8 +152,8 @@ + "\n and dogc.pd_context_id = dgc.pd_object_id" + "\n and dgc.pd_context_id = dp.pd_object_id" + "\n and dp.pd_grantee_id = dgm.pd_group_id" -+ "\n and dgm.pd_member_id = " + userID -+ "\n and " + TREE_DESCRIPTOR.constructPrivilegeClause("dp") ++ "\n and dgm.pd_member_id in (-200," + userID + ",-202)" ++ "\n and dp." + TREE_DESCRIPTOR.getColumnName() + " = 1" + "\n ) )" + "\n where i.parent_id = " + node.getID() + "\n and f.folder_id = i.item_id" @@ -168,7 +168,7 @@ + "\n and dgm.pd_member_id in (-200," + userID + ",-202)" + "\n and dp.pd_grantee_id = dgm.pd_group_id" + "\n and dogc.pd_object_id = f.folder_id" -+ "\n and " + TREE_DESCRIPTOR.constructPrivilegeClause("dp") + ")" ++ "\n and dp." + TREE_DESCRIPTOR.getColumnName() + " = 1 )" + "\n group by f.label, f.folder_id" + "\n order by lower(f.label)" ; |
From: <ssk...@vh...> - 2006-09-01 11:34:39
|
Author: sskracic Date: 2006-09-01 13:27:09 +0200 (Fri, 01 Sep 2006) New Revision: 1307 Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java Log: Don't go to database every time we need the list of implying privileges. Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java 2006-09-01 11:00:05 UTC (rev 1306) +++ trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java 2006-09-01 11:27:09 UTC (rev 1307) @@ -92,7 +92,9 @@ private String m_columnName; + private Collection m_implyingPrivs; + /** * * Adds a privilege to the system. @@ -286,15 +288,18 @@ * Returns the list of privilege names that imply this privilege. * @return a collection of the privilege names that imply this privilege. */ - public Collection getImplyingPrivilegeNames() { - Collection impliedPrivileges = new HashSet(); + public synchronized Collection getImplyingPrivilegeNames() { + if (m_implyingPrivs != null) { + return m_implyingPrivs; + } + m_implyingPrivs = new HashSet(); DataQuery query = SessionManager.getSession() .retrieveQuery("com.arsdigita.kernel.permissions.ImpliedPrivilege"); query.setParameter("childPrivilege", m_name); while (query.next()) { - impliedPrivileges.add((String)query.get("privilege")); + m_implyingPrivs.add((String)query.get("privilege")); } - return impliedPrivileges; + return m_implyingPrivs; } /** |
From: <ssk...@vh...> - 2006-09-01 11:07:36
|
Author: sskracic Date: 2006-09-01 13:00:05 +0200 (Fri, 01 Sep 2006) New Revision: 1306 Modified: trunk/ccm-cms/src/com/arsdigita/cms/ContentSection.java Log: Granting READ privilege on the staff group is wrong idea. The PermissionService.clonePermissions() will find this privilege and copy it when switching to custom permissions for a CMS folder. But, since it's not a cms_ privilege, it will not be displayed in UI and there will be no way to actually revoke this privilege. Modified: trunk/ccm-cms/src/com/arsdigita/cms/ContentSection.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ContentSection.java 2006-09-01 10:51:55 UTC (rev 1305) +++ trunk/ccm-cms/src/com/arsdigita/cms/ContentSection.java 2006-09-01 11:00:05 UTC (rev 1306) @@ -35,9 +35,7 @@ import com.arsdigita.globalization.Locale; import com.arsdigita.kernel.Group; import com.arsdigita.kernel.SiteNode; -import com.arsdigita.kernel.permissions.PermissionDescriptor; import com.arsdigita.kernel.permissions.PermissionService; -import com.arsdigita.kernel.permissions.PrivilegeDescriptor; import com.arsdigita.persistence.DataAssociation; import com.arsdigita.persistence.DataAssociationCursor; import com.arsdigita.persistence.DataCollection; @@ -1263,11 +1261,6 @@ setTemplateResolverClass(trc); save(); - // Grant the READ permission to the staff group on the content section. - PermissionDescriptor perm = - new PermissionDescriptor(PrivilegeDescriptor.READ, this, staff); - PermissionService.grantPermission(perm); - return this; } |
From: <ssk...@vh...> - 2006-09-01 10:59:25
|
Author: sskracic Date: 2006-09-01 12:51:55 +0200 (Fri, 01 Sep 2006) New Revision: 1305 Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java Log: Folder listing must be filtered through permission filter. Really. Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java 2006-09-01 09:39:57 UTC (rev 1304) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderBrowser.java 2006-09-01 10:51:55 UTC (rev 1305) @@ -20,6 +20,7 @@ import com.arsdigita.bebop.Component; import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Image; import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Link; import com.arsdigita.bebop.Page; @@ -27,6 +28,7 @@ import com.arsdigita.bebop.PaginationModelBuilder; import com.arsdigita.bebop.Paginator; import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.SimpleContainer; import com.arsdigita.bebop.Table; import com.arsdigita.bebop.event.ActionEvent; import com.arsdigita.bebop.event.ActionListener; @@ -40,8 +42,6 @@ import com.arsdigita.bebop.table.TableColumn; import com.arsdigita.bebop.table.TableHeader; import com.arsdigita.bebop.table.TableModel; -import com.arsdigita.bebop.SimpleContainer; -import com.arsdigita.bebop.Image; import com.arsdigita.cms.CMS; import com.arsdigita.cms.ContentBundle; import com.arsdigita.cms.ContentItem; @@ -56,6 +56,9 @@ import com.arsdigita.domain.DomainObject; import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; import com.arsdigita.persistence.OID; import com.arsdigita.toolbox.ui.FormatStandards; import com.arsdigita.util.Assert; @@ -267,6 +270,13 @@ return 0; } + PermissionService.filterQuery( + itemColl, + "id", + PrivilegeDescriptor.READ, + Kernel.getContext().getParty().getOID() + ); + size = new Integer( (int) f.getPrimaryInstances().size()); itemColl.setRange(new Integer(paginator.getFirst(state)), |
From: <ssk...@vh...> - 2006-09-01 09:47:34
|
Author: sskracic Date: 2006-09-01 11:39:57 +0200 (Fri, 01 Sep 2006) New Revision: 1304 Modified: trunk/ccm-cms/src/com/arsdigita/cms/workflow/CMSTask.java Log: If we were to use array[9], it would be a wise thing to allocate 10 elements in array. Modified: trunk/ccm-cms/src/com/arsdigita/cms/workflow/CMSTask.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/workflow/CMSTask.java 2006-09-01 08:54:11 UTC (rev 1303) +++ trunk/ccm-cms/src/com/arsdigita/cms/workflow/CMSTask.java 2006-09-01 09:39:57 UTC (rev 1304) @@ -254,7 +254,7 @@ String authoringURL = getAuthoringURL(item); String fullURL = URL.there(getTaskType().getURLGenerator(operation).generateURL(item.getID(), getID()), null).getURL(); // see CMSResources.properties for how these values are used - Object[] g11nArgs = new Object[9]; + Object[] g11nArgs = new Object[10]; // cg - make this configurable. Because our content section managers have access to all // folders, they get all notifications, but they want to know which area it relates to - // first folder in item path tells them. config parameter - full item path or just display name |
From: <ssk...@vh...> - 2006-09-01 09:01:52
|
Author: sskracic Date: 2006-09-01 10:54:11 +0200 (Fri, 01 Sep 2006) New Revision: 1303 Added: trunk/ccm-cms/sql/ccm-cms/default/content-section/insert-acs_privilege_hierarchy.sql Modified: trunk/ccm-cms/sql/ccm-cms/oracle-se-create.sql trunk/ccm-cms/sql/ccm-cms/postgres-create.sql Log: Privilege hierarchy needs to be correctly initialised on a fresh startup. Added: trunk/ccm-cms/sql/ccm-cms/default/content-section/insert-acs_privilege_hierarchy.sql =================================================================== --- trunk/ccm-cms/sql/ccm-cms/default/content-section/insert-acs_privilege_hierarchy.sql 2006-08-31 13:12:47 UTC (rev 1302) +++ trunk/ccm-cms/sql/ccm-cms/default/content-section/insert-acs_privilege_hierarchy.sql 2006-09-01 08:54:11 UTC (rev 1303) @@ -0,0 +1,22 @@ +-- +-- Copyright (C) 2006 Red Hat Inc. All Rights Reserved. +-- +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public License +-- as published by the Free Software Foundation; either version 2.1 of +-- the License, or (at your option) any later version. +-- +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-- +-- $Id$ + +insert into acs_privilege_hierarchy (privilege, child_privilege) + values ('cms_read_item', 'read'); + Property changes on: trunk/ccm-cms/sql/ccm-cms/default/content-section/insert-acs_privilege_hierarchy.sql ___________________________________________________________________ Name: svn:keywords + Id Author URL Modified: trunk/ccm-cms/sql/ccm-cms/oracle-se-create.sql =================================================================== --- trunk/ccm-cms/sql/ccm-cms/oracle-se-create.sql 2006-08-31 13:12:47 UTC (rev 1302) +++ trunk/ccm-cms/sql/ccm-cms/oracle-se-create.sql 2006-09-01 08:54:11 UTC (rev 1303) @@ -22,6 +22,7 @@ @@ default/content-section/table-cms_privileges.sql @@ default/content-section/insert-privileges.sql +@@ default/content-section/insert-acs_privilege_hierarchy.sql @@ default/content-section/index-phase_def_cycle_definition_idx.sql @@ default/content-section/index-lifecycles_definition_id_idx.sql @@ default/content-section/index-phases_definition_id_idx.sql Modified: trunk/ccm-cms/sql/ccm-cms/postgres-create.sql =================================================================== --- trunk/ccm-cms/sql/ccm-cms/postgres-create.sql 2006-08-31 13:12:47 UTC (rev 1302) +++ trunk/ccm-cms/sql/ccm-cms/postgres-create.sql 2006-09-01 08:54:11 UTC (rev 1303) @@ -22,6 +22,7 @@ \i default/content-section/table-cms_privileges.sql \i default/content-section/insert-privileges.sql +\i default/content-section/insert-acs_privilege_hierarchy.sql \i default/content-section/index-phase_def_cycle_definition_idx.sql \i default/content-section/index-lifecycles_definition_id_idx.sql \i default/content-section/index-phases_definition_id_idx.sql |
From: <ssk...@vh...> - 2006-08-31 13:20:16
|
Author: sskracic Date: 2006-08-31 15:12:47 +0200 (Thu, 31 Aug 2006) New Revision: 1302 Modified: trunk/ccm-core/src/com/arsdigita/persistence/DataQueryImpl.java Log: Added some logging in case SQL parser barfs. Modified: trunk/ccm-core/src/com/arsdigita/persistence/DataQueryImpl.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/persistence/DataQueryImpl.java 2006-08-31 13:10:53 UTC (rev 1301) +++ trunk/ccm-core/src/com/arsdigita/persistence/DataQueryImpl.java 2006-08-31 13:12:47 UTC (rev 1302) @@ -715,6 +715,7 @@ try { p.sql(); } catch (ParseException e) { + s_log.warn("Could not parse SQL: " + expr); throw new IllegalArgumentException(e.getMessage()); } |
From: <ssk...@vh...> - 2006-08-31 13:18:23
|
Author: sskracic Date: 2006-08-31 15:10:53 +0200 (Thu, 31 Aug 2006) New Revision: 1301 Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java Log: Fixing the breakage I've introduced in r1298 (omitted closing parenthesis). Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java 2006-08-31 12:45:24 UTC (rev 1300) +++ trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java 2006-08-31 13:10:53 UTC (rev 1301) @@ -531,7 +531,7 @@ Filter f = factory.simple( " exists ( com.arsdigita.kernel.permissions.PartyPermissionFilterQuery" + " and RAW[dogc.pd_object_id] = " + propertyName - + " and RAW[" + privilege.constructPrivilegeClause(null) + "]"); + + " and RAW[" + privilege.constructPrivilegeClause(null) + "] )"); f.set("partyID", constructAccessList(partyOID));//partyOID.get("id")); return f; } @@ -547,7 +547,7 @@ Filter f = factory.simple( " exists ( com.arsdigita.kernel.permissions.ObjectPermissionFilterQuery" + " and RAW[dgm.pd_member_id] = " + propertyName - + " and RAW[" + privilege.constructPrivilegeClause(null) + "]"); + + " and RAW[" + privilege.constructPrivilegeClause(null) + "] )"); f.set("objectID", objectOID.get("id")); return f; } |
From: <ssk...@vh...> - 2006-08-31 12:52:56
|
Author: sskracic Date: 2006-08-31 14:45:24 +0200 (Thu, 31 Aug 2006) New Revision: 1300 Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java Log: Lowered log message severity. Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java 2006-08-31 11:57:05 UTC (rev 1299) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java 2006-08-31 12:45:24 UTC (rev 1300) @@ -172,7 +172,9 @@ + "\n group by f.label, f.folder_id" + "\n order by lower(f.label)" ; - s_log.warn("SQL: \n" + sql); + if (s_log.isDebugEnabled()) { + s_log.debug("Custom SQL: \n" + sql); + } m_nodes = new GenericDataQuery( SessionManager.getSession(), |
From: <ssk...@vh...> - 2006-08-31 12:04:36
|
Author: sskracic Date: 2006-08-31 13:57:05 +0200 (Thu, 31 Aug 2006) New Revision: 1299 Modified: trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java Log: The folder browser query had 2 big issues: 1. the outer permission check was being performed on the single privilege only, instead of checking for all implying privileges 2. the inner permission check (in the query which counts the number of visible children each folder has) was producing the correct results b/c it was normal permissioning/privileges tables. However, this resulted in terrible performance problems. Due to way the persistence wrap queries, it was not possible to apply a dynamically generated filter to the inner query (actually, you can't apply any kind of filter to inner query[es]). So the only solution was to switch to completely dynamical SQL, which now queries denormalised permissioning tables for both inner and outer parts of the folder browser query. Modified: trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl =================================================================== --- trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl 2006-08-31 11:18:12 UTC (rev 1298) +++ trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.ora.pdl 2006-08-31 11:57:05 UTC (rev 1299) @@ -26,7 +26,7 @@ String name; BigDecimal nchild; do { - select f.label, + select f.label, f.folder_id, count(sub.item_id) as sub_count from cms_folders f, @@ -59,12 +59,12 @@ from cms_folders f, cms_items i where f.folder_id = i.item_id - ) sub + ) sub where i.parent_id = :objectID and f.folder_id = i.item_id and sub.parent_id(+) = i.item_id group by f.label, f.folder_id - order by lower(f.label) + order by lower(f.label) } map { id = f.folder_id; name = f.label; @@ -73,46 +73,7 @@ } -query getSubFoldersWithPermissions { - BigDecimal id; - String name; - BigDecimal nchild; - do { - select f.label, - f.folder_id, - count(sub.item_id) as sub_count - from cms_folders f, - cms_items i, - (select i.item_id, i.parent_id - from cms_folders f, - cms_items i - where f.folder_id = i.item_id - and exists (select 1 - from dnm_object_1_granted_context dogc, - dnm_granted_context dgc, - acs_permissions ap, - dnm_group_membership dgm - where dogc.pd_object_id = i.item_id - and dogc.pd_context_id = dgc.pd_object_id - and dgc.pd_context_id = ap.object_id - and ap.grantee_id = dgm.pd_group_id - and dgm.pd_member_id = :party - and ap.privilege in (select pd_child_privilege - from dnm_privilege_hierarchy_map - where pd_privilege = :priv))) sub - where i.parent_id = :objectID - and f.folder_id = i.item_id - and sub.parent_id(+) = i.item_id - group by f.label, f.folder_id - order by lower(f.label) - } map { - id = f.folder_id; - name = f.label; - nchild = sub_count; - } -} - // // Modified for Multilingual Content: // it expects that direct children of the Folder @@ -120,24 +81,24 @@ // NOTE: If you are running Oracle 9.2.0.3 or higher, // the following query may be faster: -// select +// select // a.object_type, a.display_name, a.default_domain_class, -// i.master_id, +// i.master_id, // i.item_id, i.parent_id, i.version, i.name, // case when exists (select 1 // from cms_items // where master_id = i.item_id) // then 1 else 0 end as has_live_version, -// case when exists (select 1 +// case when exists (select 1 // from cms_folders f -// where i.item_id = f.folder_id) -// then 1 else 0 end as is_folder -// from -// cms_items i, +// where i.item_id = f.folder_id) +// then 1 else 0 end as is_folder +// from +// cms_items i, // acs_objects a -// where +// where // i.item_id = a.object_id -// and +// and // i.parent_id = :parent // and // i.version = :version @@ -145,7 +106,7 @@ // where f.folder_id = i.item_id) // or // exists (select 1 from cms_bundles b -// where b.bundle_id = i.item_id)) +// where b.bundle_id = i.item_id)) // //But, it will crash versions of Oracle prior to 9.2.0.3 query ItemsInFolder { @@ -155,7 +116,7 @@ Boolean hasLiveVersion; do { - select + select a.object_type, a.display_name, a.default_domain_class, i.master_id, i.item_id, i.parent_id, i.version, i.name, i.type_id, t.label, @@ -164,18 +125,18 @@ where master_id = i.item_id) then 1 else 0 end as has_live_version, case when 0 = nvl(f.folder_id, 0) then 0 else 1 end as is_folder - from - cms_items i, - acs_objects a, + from + cms_items i, + acs_objects a, cms_folders f, content_types t - where + where i.item_id = a.object_id - and + and i.item_id = f.folder_id(+) - and + and i.type_id = t.type_id(+) - and + and i.parent_id = :parent and i.version = :version @@ -183,7 +144,7 @@ where f.folder_id = i.item_id) or exists (select 1 from cms_bundles b - where b.bundle_id = i.item_id)) + where b.bundle_id = i.item_id)) } map { item.id = i.item_id; item.objectType = a.object_type; @@ -215,7 +176,7 @@ BasicAuditTrail auditTrail; do { - select + select a.object_type, a.display_name, a.default_domain_class, i.item_id, i.parent_id, i.version, i.name, i.master_id, aud.modifying_ip, aud.last_modified, aud.creation_date, aud.creation_ip, @@ -226,23 +187,23 @@ then 1 else 0 end as has_live_version, 0 as type_id, '' as label, 0 as bundle_id - from - cms_items i, - cms_folders f, + from + cms_items i, + cms_folders f, acs_objects a, acs_auditing aud - where + where i.item_id = a.object_id - and + and i.item_id = f.folder_id - and + and i.item_id = aud.object_id - and + and i.parent_id = :parent and i.version = :version UNION ALL - select + select a.object_type, a.display_name, a.default_domain_class, i.item_id, i.parent_id, i.version, i.name, i.master_id, aud.modifying_ip, aud.last_modified, aud.creation_date, aud.creation_ip, @@ -253,20 +214,20 @@ then 1 else 0 end as has_live_version, t.type_id as type_id, t.label as label, b.bundle_id as bundle_id - from - cms_items i, + from + cms_items i, cms_bundles b, - cms_items bi, - acs_objects a, + cms_items bi, + acs_objects a, content_types t, acs_auditing aud - where + where i.item_id = a.object_id - and + and i.type_id = t.type_id and i.item_id = aud.object_id - and + and i.language = b.default_language and i.parent_id = b.bundle_id Modified: trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl =================================================================== --- trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl 2006-08-31 11:18:12 UTC (rev 1298) +++ trunk/ccm-cms/pdl/com/arsdigita/content-section/Folder-queries.pg.pdl 2006-08-31 11:57:05 UTC (rev 1299) @@ -26,14 +26,14 @@ String name; BigDecimal nchild; do { - select f.label, + select f.label, f.folder_id, count(sub.item_id) as sub_count from cms_folders f left join (select i.item_id, i.parent_id from cms_folders f, cms_items i - where f.folder_id = i.item_id) sub on + where f.folder_id = i.item_id) sub on (f.folder_id = sub.parent_id) where f.folder_id = :objectID group by f.label, f.folder_id @@ -63,7 +63,7 @@ where i.parent_id = :objectID and f.folder_id = i.item_id group by f.label, f.folder_id - order by lower(f.label) + order by lower(f.label) } map { id = f.folder_id; name = f.label; @@ -72,45 +72,6 @@ } -query getSubFoldersWithPermissions { - BigDecimal id; - String name; - BigDecimal nchild; - do { - select f.label, - f.folder_id, - count(sub.item_id) as sub_count - from cms_folders f, - cms_items i - left join - (select i.item_id, i.parent_id - from cms_folders f, - cms_items i - where f.folder_id = i.item_id - and exists (select 1 - from dnm_object_1_granted_context dogc, - dnm_granted_context dgc, - acs_permissions ap, - dnm_group_membership dgm - where dogc.pd_object_id = i.item_id - and dogc.pd_context_id = dgc.pd_object_id - and dgc.pd_context_id = ap.object_id - and ap.grantee_id = dgm.pd_group_id - and dgm.pd_member_id = :party - and ap.privilege in (select pd_privilege - from dnm_privilege_hierarchy_map - where pd_child_privilege = :priv))) sub on (sub.parent_id = i.item_id) - where i.parent_id = :objectID - and f.folder_id = i.item_id - group by f.label, f.folder_id - order by lower(f.label) - } map { - id = f.folder_id; - name = f.label; - nchild = sub_count; - } -} - // // Modified for Multilingual Content: // it expects that direct children of the Folder @@ -123,26 +84,26 @@ Boolean hasLiveVersion; do { - select + select a.object_type, a.display_name, a.default_domain_class, - i.master_id, + i.master_id, i.item_id, i.parent_id, i.version, i.name, t.type_id, t.label, case when exists (select 1 from cms_items where master_id = i.item_id) then 1 else 0 end as has_live_version, - case when exists (select 1 + case when exists (select 1 from cms_folders f - where i.item_id = f.folder_id) + where i.item_id = f.folder_id) then 1 else 0 end as is_folder - from + from acs_objects a, - cms_items i + cms_items i left join content_types t on (t.type_id = i.type_id) - where + where i.item_id = a.object_id - and + and i.parent_id = :parent and i.version = :version @@ -150,7 +111,7 @@ where f.folder_id = i.item_id) or exists (select 1 from cms_bundles b - where b.bundle_id = i.item_id)) + where b.bundle_id = i.item_id)) } map { item.id = i.item_id; item.objectType = a.object_type; @@ -180,7 +141,7 @@ BasicAuditTrail auditTrail; do { - select + select a.object_type, a.display_name, a.default_domain_class, i.item_id, i.parent_id, i.version, i.name, i.master_id, aud.modifying_ip, aud.last_modified, aud.creation_date, aud.creation_ip, @@ -191,23 +152,23 @@ then 1 else 0 end as has_live_version, 0 as type_id, '' as label, 0 as bundle_id - from - cms_items i, - cms_folders f, + from + cms_items i, + cms_folders f, acs_objects a, acs_auditing aud - where + where i.item_id = a.object_id - and + and i.item_id = aud.object_id - and + and i.item_id = f.folder_id - and + and i.parent_id = :parent and i.version = :version UNION ALL - select + select a.object_type, a.display_name, a.default_domain_class, i.item_id, i.parent_id, i.version, i.name, i.master_id, aud.modifying_ip, aud.last_modified, aud.creation_date, aud.creation_ip, @@ -218,20 +179,20 @@ then 1 else 0 end as has_live_version, t.type_id as type_id, t.label as label, b.bundle_id as bundle_id - from - cms_items i, + from + cms_items i, cms_bundles b, - cms_items bi, - acs_objects a, + cms_items bi, + acs_objects a, content_types t, acs_auditing aud - where + where i.item_id = a.object_id - and + and i.item_id = aud.object_id - and + and i.type_id = t.type_id - and + and i.language = b.default_language and i.parent_id = b.bundle_id Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java 2006-08-31 11:18:12 UTC (rev 1298) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java 2006-08-31 11:57:05 UTC (rev 1299) @@ -18,7 +18,6 @@ */ package com.arsdigita.cms.ui.folder; - import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.Tree; import com.arsdigita.bebop.tree.TreeModelBuilder; @@ -27,7 +26,6 @@ import com.arsdigita.cms.ContentSection; import com.arsdigita.cms.Folder; import com.arsdigita.cms.SecurityManager; -import com.arsdigita.kernel.ACSObject; import com.arsdigita.kernel.Kernel; import com.arsdigita.kernel.Party; import com.arsdigita.kernel.User; @@ -35,13 +33,16 @@ import com.arsdigita.kernel.permissions.PermissionService; import com.arsdigita.kernel.permissions.PrivilegeDescriptor; import com.arsdigita.kernel.permissions.UniversalPermissionDescriptor; -import com.arsdigita.kernel.ui.DataQueryTreeIterator; import com.arsdigita.kernel.ui.DataQueryTreeModel; import com.arsdigita.kernel.ui.DataQueryTreeNode; +import com.arsdigita.persistence.GenericDataQuery; import com.arsdigita.persistence.OID; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.DataQuery; import com.arsdigita.util.LockableImpl; - +import java.math.BigDecimal; import java.util.Iterator; +import org.apache.log4j.Logger; /** @@ -58,9 +59,11 @@ public class FolderTreeModelBuilder extends LockableImpl implements TreeModelBuilder { + private static final Logger s_log = Logger.getLogger(FolderTreeModelBuilder.class); + public static final String versionId = "$Id$ by $Author$, $DateTime: 2004/08/17 23:15:09 $"; - private PrivilegeDescriptor TREE_DESCRIPTOR = + private PrivilegeDescriptor TREE_DESCRIPTOR = SecurityManager.CMS_PREVIEW_ITEM_DESCRIPTOR; /** * Make a tree model that lists the hierarchy of folders underneath the @@ -75,22 +78,12 @@ return new DataQueryTreeModel(getRoot(s).getID(), "com.arsdigita.cms.getRootFolder", "com.arsdigita.cms.getSubFolders") { - protected DataQueryTreeIterator getDataQueryTreeIterator - (DataQueryTreeNode node, String getSubCategories) { - DataQueryTreeIterator iterator = - new DataQueryTreeIterator(node, getSubCategories); - iterator.filterQuery - (ACSObject.ID, - TREE_DESCRIPTOR, - Kernel.getContext().getParty().getOID()); - return iterator; - } public Iterator getChildren(TreeNode node, PageState data) { Party party = Kernel.getContext().getParty(); OID partyOID = null; if (party == null) { - partyOID = new OID(User.BASE_DATA_OBJECT_TYPE, + partyOID = new OID(User.BASE_DATA_OBJECT_TYPE, PermissionManager.VIRTUAL_PUBLIC_ID); } else { partyOID = party.getOID(); @@ -102,20 +95,14 @@ (universalPermission)) { // the person is an admin so we just pass in the // standard, non filtered query - return getDataQueryTreeIterator - ((DataQueryTreeNode)node, + return getDataQueryTreeIterator( + (DataQueryTreeNode) node, "com.arsdigita.cms.getSubFolders"); } else { - DataQueryTreeIterator iterator = - getDataQueryTreeIterator - ((DataQueryTreeNode)node, - "com.arsdigita.cms.getSubFoldersWithPermissions"); // now we need to set the parameters - iterator.setParameter - ("party", partyOID.get("id")); - iterator.setParameter - ("priv", TREE_DESCRIPTOR.getName()); - return iterator; + return new NewFolderBrowserIterator( + (DataQueryTreeNode) node, + partyOID); } } }; @@ -135,4 +122,90 @@ } + private class NewFolderBrowserIterator implements Iterator { + + private DataQuery m_nodes; + + public NewFolderBrowserIterator(DataQueryTreeNode node, OID partyOID) { + + BigDecimal userID = (BigDecimal) partyOID.get("id"); + + String sql = "" ++ "\n select f.folder_id as id," ++ "\n f.label as name," ++ "\n count(sub.item_id) as nchild" ++ "\n from cms_folders f," ++ "\n cms_items i" ++ "\n left join" ++ "\n (select i2.item_id, f2.label as name, i2.parent_id" ++ "\n from cms_folders f2," ++ "\n cms_items i2" ++ "\n where f2.folder_id = i2.item_id) sub" ++ "\n on (sub.parent_id = i.item_id" ++ "\n and" ++ "\n exists (select 1" ++ "\n from dnm_object_1_granted_context dogc," ++ "\n dnm_granted_context dgc," ++ "\n dnm_permissions dp," ++ "\n dnm_group_membership dgm" ++ "\n where dogc.pd_object_id = sub.item_id" ++ "\n and dogc.pd_context_id = dgc.pd_object_id" ++ "\n and dgc.pd_context_id = dp.pd_object_id" ++ "\n and dp.pd_grantee_id = dgm.pd_group_id" ++ "\n and dgm.pd_member_id = " + userID ++ "\n and " + TREE_DESCRIPTOR.constructPrivilegeClause("dp") ++ "\n ) )" ++ "\n where i.parent_id = " + node.getID() ++ "\n and f.folder_id = i.item_id" ++ "\n and exists (" ++ "\n select 1 as permission_p" ++ "\n from dnm_object_1_granted_context dogc," ++ "\n dnm_granted_context dgc," ++ "\n dnm_permissions dp," ++ "\n dnm_group_membership dgm" ++ "\n where dogc.pd_context_id = dgc.pd_object_id" ++ "\n and dgc.pd_context_id = dp.pd_object_id" ++ "\n and dgm.pd_member_id in (-200," + userID + ",-202)" ++ "\n and dp.pd_grantee_id = dgm.pd_group_id" ++ "\n and dogc.pd_object_id = f.folder_id" ++ "\n and " + TREE_DESCRIPTOR.constructPrivilegeClause("dp") + ")" ++ "\n group by f.label, f.folder_id" ++ "\n order by lower(f.label)" ; + + s_log.warn("SQL: \n" + sql); + + m_nodes = new GenericDataQuery( + SessionManager.getSession(), + sql, + new String[] {"id", "name", "nchild"} + ); + } + + public Object next() { + BigDecimal id = new BigDecimal(0); + try { + // this appears to be the only portable way to dig numbers out + // of the result set + id = new BigDecimal(m_nodes.get("id").toString()); + } catch (NumberFormatException nfe) {} + String name = m_nodes.get("name").toString(); + BigDecimal count = new BigDecimal(0); + try { + count = new BigDecimal(m_nodes.get("nchild").toString()); + } catch (NumberFormatException nfe) {} + + return new DataQueryTreeNode(id, name, count.intValue() > 0); + } + + public void remove() { + throw new UnsupportedOperationException + ("cannot remove nodes via iterator"); + } + + public boolean hasNext() { + return m_nodes.next(); + } + + } + } |
From: <ssk...@vh...> - 2006-08-31 11:25:43
|
Author: sskracic Date: 2006-08-31 13:18:12 +0200 (Thu, 31 Aug 2006) New Revision: 1298 Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java Log: Moved contructPrivilegeClause into public method of PrivilegeDescriptor, since it can be useful with dynamically generated SQL. Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java 2006-08-29 13:26:32 UTC (rev 1297) +++ trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java 2006-08-31 11:18:12 UTC (rev 1298) @@ -531,7 +531,7 @@ Filter f = factory.simple( " exists ( com.arsdigita.kernel.permissions.PartyPermissionFilterQuery" + " and RAW[dogc.pd_object_id] = " + propertyName - + " and " + constructPrivilegeList(privilege) + ")"); + + " and RAW[" + privilege.constructPrivilegeClause(null) + "]"); f.set("partyID", constructAccessList(partyOID));//partyOID.get("id")); return f; } @@ -547,7 +547,7 @@ Filter f = factory.simple( " exists ( com.arsdigita.kernel.permissions.ObjectPermissionFilterQuery" + " and RAW[dgm.pd_member_id] = " + propertyName - + " and " + constructPrivilegeList(privilege) + ")"); + + " and RAW[" + privilege.constructPrivilegeClause(null) + "]"); f.set("objectID", objectOID.get("id")); return f; } @@ -714,33 +714,6 @@ /** - * Given a privilege descripter, constructs a clause - * where the column names matched to all privileges that imply given - * privilege are ORed together. - * - * @param priv a privilege to construct the clause for - * @return SQL string that should be fed directly to database - */ - private String constructPrivilegeList(PrivilegeDescriptor priv) { - Iterator it = priv.getImplyingPrivilegeNames().iterator(); - StringBuffer sql = null; - while (it.hasNext()) { - if (sql == null) { - sql = new StringBuffer(100); - sql.append("("); - } else { - sql.append(" or "); - } - PrivilegeDescriptor implyingPriv = PrivilegeDescriptor.get( (String) it.next()); - sql.append("RAW[" + implyingPriv.getColumnName() + " = 1 ]"); - } - - sql.append(")"); - return sql.toString(); - } - - - /** * this takes in an OID and returns the public OID if the passed in * value is null. Otherwise, it returns the passed in value. */ Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java 2006-08-29 13:26:32 UTC (rev 1297) +++ trunk/ccm-core/src/com/arsdigita/kernel/permissions/PrivilegeDescriptor.java 2006-08-31 11:18:12 UTC (rev 1298) @@ -29,6 +29,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; /** @@ -336,4 +337,34 @@ privs.close(); } + + /** + * Constructs a SQL clause ready to test for this privilege against + * the denormalised permission table where each privilege is represented + * with its own column. All column tests are ORed together. + * + * @param alias optional alias for dnm_permissions table, if null then + * no alias will be prepended to column names + * @return SQL string that should be fed directly to database + */ + public String constructPrivilegeClause(String alias) { + Iterator it = getImplyingPrivilegeNames().iterator(); + StringBuffer sql = null; + while (it.hasNext()) { + if (sql == null) { + sql = new StringBuffer(100); + sql.append("("); + } else { + sql.append(" or "); + } + PrivilegeDescriptor implyingPriv = PrivilegeDescriptor.get( (String) it.next()); + if (alias != null) { + sql.append(alias + "."); + } + sql.append(implyingPriv.getColumnName() + " = 1"); + } + sql.append(")"); + return sql.toString(); + } + } |
From: <ssk...@vh...> - 2006-08-29 13:34:00
|
Author: sskracic Date: 2006-08-29 15:26:32 +0200 (Tue, 29 Aug 2006) New Revision: 1297 Modified: trunk/ccm-core/src/com/redhat/persistence/engine/rdbms/RDBMSRecordSet.java Log: A typo. Modified: trunk/ccm-core/src/com/redhat/persistence/engine/rdbms/RDBMSRecordSet.java =================================================================== --- trunk/ccm-core/src/com/redhat/persistence/engine/rdbms/RDBMSRecordSet.java 2006-08-28 10:34:11 UTC (rev 1296) +++ trunk/ccm-core/src/com/redhat/persistence/engine/rdbms/RDBMSRecordSet.java 2006-08-29 13:26:32 UTC (rev 1297) @@ -39,7 +39,7 @@ public final static String versionId = "$Id$ by $Author$, $DateTime: 2004/08/16 18:10:38 $"; - private static final Logger s_log = Logger.getLogger(RecordSet.class); + private static final Logger s_log = Logger.getLogger(RDBMSRecordSet.class); final private RDBMSEngine m_engine; final private ResultCycle m_rc; |
From: <ssk...@vh...> - 2006-08-28 10:41:34
|
Author: sskracic Date: 2006-08-28 12:34:11 +0200 (Mon, 28 Aug 2006) New Revision: 1296 Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java Log: When checking the denormalised permissions or privileges, we must manually expand to check for all implying privileges as well. Modified: trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java =================================================================== --- trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java 2006-08-25 18:17:50 UTC (rev 1295) +++ trunk/ccm-core/src/com/arsdigita/kernel/permissions/PermissionManager.java 2006-08-28 10:34:11 UTC (rev 1296) @@ -97,31 +97,31 @@ } boolean checkDirectPermission( - PermissionDescriptor permission, - boolean useImpliedPrivs) { + PermissionDescriptor permission, + boolean useImpliedPrivs) { - if (useImpliedPrivs) { - return doCheck("CheckDirectGrantWithImpliedPrivileges", permission); - } else { - DataQuery query = getQuery("CheckDirectGrant"); - query.setParameter( - "privilege", - permission.getPrivilegeDescriptor().getName()); + if (useImpliedPrivs) { + return doCheck("CheckDirectGrantWithImpliedPrivileges", permission); + } else { + DataQuery query = getQuery("CheckDirectGrant"); + query.setParameter( + "privilege", + permission.getPrivilegeDescriptor().getName()); - query.setParameter( - "objectID", - permission.getACSObjectOID().get("id")); - query.setParameter("partyID", constructAccessList(permission.getPartyOID())); + query.setParameter( + "objectID", + permission.getACSObjectOID().get("id")); + query.setParameter("partyID", constructAccessList(permission.getPartyOID())); - if (query.next()) { - query.close(); - return true; - } else { - query.close(); - return false; - } - } - } + if (query.next()) { + query.close(); + return true; + } else { + query.close(); + return false; + } + } + } /** * Check a universal permission. This will soon be optimized via @@ -136,10 +136,10 @@ private boolean doCheck(String queryName, PermissionDescriptor permission) { DataQuery query = getQuery("PermissionCheckPlaceholder"); - - Filter f = query.addFilter(" exists ( com.arsdigita.kernel.permissions." - + queryName + " and RAW[" - + permission.getPrivilegeDescriptor().getColumnName() + " = 1 ])"); + + Filter f = query.addFilter(" exists ( com.arsdigita.kernel.permissions." + + queryName + " and RAW[" + + permission.getPrivilegeDescriptor().getColumnName() + " = 1 ])"); f.set("objectID", permission.getACSObjectOID().get("id")); f.set("partyID", constructAccessList(permission.getPartyOID()));//.get("id")); @@ -151,8 +151,8 @@ return false; } } - - + + /** * Grants the permission as * specified by the PermissionDescriptor @@ -527,10 +527,11 @@ if (!checkPermission(universalPermission)) { + Filter f = factory.simple( " exists ( com.arsdigita.kernel.permissions.PartyPermissionFilterQuery" - + " and RAW[dogc.pd_object_id] = " + propertyName - + " and RAW[" + privilege.getColumnName() + " = 1 ])"); + + " and RAW[dogc.pd_object_id] = " + propertyName + + " and " + constructPrivilegeList(privilege) + ")"); f.set("partyID", constructAccessList(partyOID));//partyOID.get("id")); return f; } @@ -543,11 +544,11 @@ String propertyName, PrivilegeDescriptor privilege, OID objectOID) { - Filter f = factory.simple( - " exists ( com.arsdigita.kernel.permissions.ObjectPermissionFilterQuery" - + " and RAW[dgm.pd_member_id] = " + propertyName - + " and RAW[" + privilege.getColumnName() + " = 1 ]) "); - f.set("objectID", objectOID.get("id")); + Filter f = factory.simple( + " exists ( com.arsdigita.kernel.permissions.ObjectPermissionFilterQuery" + + " and RAW[dgm.pd_member_id] = " + propertyName + + " and " + constructPrivilegeList(privilege) + ")"); + f.set("objectID", objectOID.get("id")); return f; } @@ -685,13 +686,13 @@ * be extended to any real User. * * This has been made "public static" instead of "private" so that - * the information can be used for an inner query in + * the information can be used for an inner query in * FolderTreeModelBuilder in CMS * @param partyOID an <code>OID</code> value * @return a <code>Collection</code> value - * + * * @deprecated this is slower than using "normal" permission checks - * since "in ("") transformed into union by Oracle SQL Optimizer + * since "in ("") transformed into union by Oracle SQL Optimizer */ public static Collection constructAccessList(OID partyOID) { ArrayList users = new ArrayList(); @@ -713,6 +714,33 @@ /** + * Given a privilege descripter, constructs a clause + * where the column names matched to all privileges that imply given + * privilege are ORed together. + * + * @param priv a privilege to construct the clause for + * @return SQL string that should be fed directly to database + */ + private String constructPrivilegeList(PrivilegeDescriptor priv) { + Iterator it = priv.getImplyingPrivilegeNames().iterator(); + StringBuffer sql = null; + while (it.hasNext()) { + if (sql == null) { + sql = new StringBuffer(100); + sql.append("("); + } else { + sql.append(" or "); + } + PrivilegeDescriptor implyingPriv = PrivilegeDescriptor.get( (String) it.next()); + sql.append("RAW[" + implyingPriv.getColumnName() + " = 1 ]"); + } + + sql.append(")"); + return sql.toString(); + } + + + /** * this takes in an OID and returns the public OID if the passed in * value is null. Otherwise, it returns the passed in value. */ |
Author: apevec Date: 2006-08-25 20:17:50 +0200 (Fri, 25 Aug 2006) New Revision: 1295 Added: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsResources.properties trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoCategoryExtension.java trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoCategoryForm.java trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoTerms.java trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/CategorySubtree.java trunk/ccm-ldn-aplaws/web/__ccm__/themes/aplaws/category-step.xsl trunk/ccm-ldn-aplaws/web/packages/content-section/www/admin/ trunk/ccm-ldn-aplaws/web/packages/content-section/www/admin/auto-cat.jsp trunk/ccm-ldn-aplaws/web/packages/content-section/www/admin/load-cat.jsp Modified: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/Aplaws.java trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsConfig.java trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsConfig_parameter.properties trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AutoCategorisation.java trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/ItemCategoryPicker.java trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/TermWidget.java trunk/ccm-ldn-aplaws/web/__ccm__/themes/aplaws/content-section-admin.xsl Log: Category step extension: use Cintra web service to automatically derive categories for the content of the item (extracted using search indexing mechanism) Also to be able to handle BIG category trees like LGCL IPSV, do not load the whole tree at once but load top-level branch at the time when it is expanded (using AJAX) *NOTE* if custom theme overrides content-section-admin.xsl it must import new web/__ccm__/themes/aplaws/category-step.xsl Modified: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/Aplaws.java =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/Aplaws.java 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/Aplaws.java 2006-08-25 18:17:50 UTC (rev 1295) @@ -24,24 +24,15 @@ public static final String versionId = "$Id$"; - private static final Logger s_log = Logger.getLogger(Aplaws.class); + private static final Logger LOG = Logger.getLogger(Aplaws.class); - private static AplawsConfig s_aplawsConfig; + private static AplawsConfig aplawsConfig = new AplawsConfig(); - private static boolean initialized = false; - - private static void init() { - if (initialized) { - return; - } - - s_aplawsConfig = new AplawsConfig(); - - initialized = true; + static { + aplawsConfig.load(); } public static final AplawsConfig getAplawsConfig() { - init(); - return s_aplawsConfig; + return aplawsConfig; } } Modified: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsConfig.java =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsConfig.java 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsConfig.java 2006-08-25 18:17:50 UTC (rev 1295) @@ -21,6 +21,7 @@ import com.arsdigita.runtime.AbstractConfig; import com.arsdigita.util.parameter.Parameter; import com.arsdigita.util.parameter.BooleanParameter; +import com.arsdigita.util.parameter.StringParameter; /** * AplawsConfig @@ -34,13 +35,29 @@ private final Parameter m_overrideAnavFromLGCLMappings = new BooleanParameter ("com.arsdigita.aplaws.override_anav_from_lgcl_mappings", Parameter.OPTIONAL, new Boolean(false)); + private final Parameter m_autocatServiceUsername = new StringParameter("com.arsdigita.aplaws.autocat_username", Parameter.OPTIONAL, null); + private final Parameter m_autocatServicePassword = new StringParameter("com.arsdigita.aplaws.autocat_password", Parameter.OPTIONAL, null); public AplawsConfig() { register(m_overrideAnavFromLGCLMappings); + register(m_autocatServiceUsername); + register(m_autocatServicePassword); loadInfo(); } public Boolean getOverrideAnavFromLGCLMappings() { return (Boolean) get(m_overrideAnavFromLGCLMappings); } + + public String getAutocatServiceUsername() { + String username = (String) get(m_autocatServiceUsername); + System.out.println("AplawsConfig username="+username); + return username; + } + + public String getAutocatServicePassword() { + String password = (String) get(m_autocatServicePassword); + System.out.println("AplawsConfig password="+password); + return password; + } } Modified: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsConfig_parameter.properties =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsConfig_parameter.properties 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsConfig_parameter.properties 2006-08-25 18:17:50 UTC (rev 1295) @@ -2,3 +2,11 @@ com.arsdigita.aplaws.override_anav_from_lgcl_mappings.purpose=If set to true, assigning one/some LGCL categories to an item will erase its existing ANav categories (and replace them with ANav categories linked to the LGCL ones, if any) com.arsdigita.aplaws.override_anav_from_lgcl_mappings.example=true|false com.arsdigita.aplaws.override_anav_from_lgcl_mappings.format=[boolean] +com.arsdigita.aplaws.autocat_username.title=Cintra service username +com.arsdigita.aplaws.autocat_username.purpose=Username for the autocategorisation web service +com.arsdigita.aplaws.autocat_username.example=user +com.arsdigita.aplaws.autocat_username.format=[string] +com.arsdigita.aplaws.autocat_password.title=Cintra service password +com.arsdigita.aplaws.autocat_password.purpose=Username for the autocategorisation web service +com.arsdigita.aplaws.autocat_password.example=pass +com.arsdigita.aplaws.autocat_password.format=[string] Added: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsResources.properties =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsResources.properties 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AplawsResources.properties 2006-08-25 18:17:50 UTC (rev 1295) @@ -0,0 +1,2 @@ +autocat.call.service=Use remote categorisation service +autocat.title=Categories returned by categorisation service \ No newline at end of file Modified: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AutoCategorisation.java =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AutoCategorisation.java 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/AutoCategorisation.java 2006-08-25 18:17:50 UTC (rev 1295) @@ -2,6 +2,7 @@ import java.io.FileReader; import java.io.IOException; +import java.io.StringReader; import java.math.BigDecimal; import java.util.Collection; import java.util.HashSet; @@ -12,9 +13,14 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import javax.xml.rpc.ParameterMode; +import org.apache.axis.Constants; +import org.apache.axis.client.Call; +import org.apache.axis.client.Service; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.OptionBuilder; +import org.apache.log4j.Logger; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -29,19 +35,24 @@ import com.arsdigita.cms.dispatcher.ItemResolver; import com.arsdigita.domain.DataObjectNotFoundException; import com.arsdigita.domain.DomainCollection; +import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.domain.DomainServiceInterfaceExposer; import com.arsdigita.london.cms.dublin.DublinCoreItem; import com.arsdigita.london.navigation.Navigation; import com.arsdigita.london.navigation.NavigationFileResolver; import com.arsdigita.london.terms.Domain; import com.arsdigita.london.terms.Term; -import com.arsdigita.london.util.Program; import com.arsdigita.persistence.DataAssociation; import com.arsdigita.persistence.DataAssociationCursor; import com.arsdigita.persistence.DataCollection; import com.arsdigita.persistence.DataObject; import com.arsdigita.persistence.Filter; +import com.arsdigita.persistence.OID; import com.arsdigita.persistence.SessionManager; +import com.arsdigita.search.ContentProvider; +import com.arsdigita.search.ContentType; +import com.arsdigita.search.MetadataProvider; +import com.arsdigita.search.MetadataProviderRegistry; import com.arsdigita.web.Application; /** * Command line tool to automatically assign terms. @@ -52,8 +63,9 @@ * * @author ap...@re... */ -public class AutoCategorisation extends Program { +public class AutoCategorisation extends com.arsdigita.packaging.Program { + private static final Logger LOG = Logger.getLogger(AutoCategorisation.class); private static final String CCM_PREFIX = "/ccm/"; private SAXParser parser; @@ -101,9 +113,6 @@ /** * Parse the XML site report from MASmedia Searchlight Indexer. - * - * @author apevec - * */ private static class SearchlightHandler extends DefaultHandler { @@ -114,7 +123,6 @@ String urlid; String url; ContentItem item; - ContentBundle bundle; String scheme; Collection keywords = new HashSet(); Collection terms = new HashSet(); @@ -154,7 +162,6 @@ urlid = null; url = null; item = null; - bundle = null; } else if ("unformated_data".equals(qName)) { keywords.clear(); terms.clear(); @@ -216,9 +223,12 @@ StringTokenizer tok = new StringTokenizer( buffer.toString(), ";"); while (tok.hasMoreTokens()) { - Term term = findTerm(scheme, tok.nextToken().trim()); + String name = tok.nextToken().trim(); + Term term = findTerm(scheme, name); if (term != null) { terms.add(term); + } else if (isVerbose) { + out("term not found " + scheme + '/' + name); } } } @@ -234,14 +244,6 @@ } } - private void out(String line) { - System.out.println(line); - } - - private void err(String line) { - System.err.println(line); - } - private void findItem() { url = buffer.toString(); // resolve url to the item @@ -352,7 +354,7 @@ private void assignTerms() { if (item != null) { - bundle = (ContentBundle) item.getParent(); + ContentBundle bundle = (ContentBundle) item.getParent(); Collection manualCategories = new HashSet(); Collection oldAutoCategories = new HashSet(); Collection newAutoCategories = new LinkedList(); @@ -500,28 +502,156 @@ } } - private Term findTerm(String domainKey, String name) { - try { - Domain domain = Domain.retrieve(domainKey); - if (domain != null) { - DomainCollection terms = domain.getTerms(); - Filter f = terms.addFilter("upper("+Term.NAME+") = :name"); - f.set("name", name.toUpperCase()); - if (terms.next()) { - Term term = (Term) terms.getDomainObject(); - terms.close(); - return term; - } else if (isVerbose) { - out("term not found " + domainKey + '/' + name); + } + + private static void out(String line) { + LOG.info(line); + } + + private static Term findTerm(String domainKey, String name) { + try { + Domain domain = Domain.retrieve(domainKey); + if (domain != null) { + DomainCollection terms = domain.getTerms(); + Filter f = terms.addFilter("upper("+Term.NAME+") = :name"); + f.set("name", name.toUpperCase()); + if (terms.next()) { + Term term = (Term) terms.getDomainObject(); + terms.close(); + return term; + } + } + } catch (DataObjectNotFoundException donfe) { + // domain not found + } + return null; + } + + /** + * Call Searchlight web service. + * Process service response and try to map detected categories to TermS. + * + * @param item content item + * @return a list of suggested TermS derived from the text extracted + * from the given content item + */ + public static Collection getAutoTerms(ContentItem item) throws ServiceFailed { + Collection terms = new HashSet(); + try { + // text extraction, see c.a.search.lucene.DocumentObserver + MetadataProvider adapter = MetadataProviderRegistry + .findAdapter(item.getObjectType()); + if (adapter != null) { + ContentProvider[] content = adapter.getContent(item, + ContentType.TEXT); + StringBuffer buf = new StringBuffer(); + for (int i = 0, n = content.length; i < n; i++) { + if (content[i].getType().equals(ContentType.TEXT)) { + buf.append(new String(content[i].getBytes())); } } - } catch (DataObjectNotFoundException donfe) { - if (isVerbose) { - out("domain not found " + domainKey); + String endpoint = "http://demo.masprovider.com/searchLightWS/services/textMiner"; + String version = "1.0"; + Service service = new Service(); + Call call = (Call) service.createCall(); + call.setTargetEndpointAddress(new java.net.URL(endpoint)); + call.setOperationName("getCategoriesAndKeywordsFromText"); + call.addParameter("text", Constants.XSD_STRING, + ParameterMode.IN); + call.addParameter("version", Constants.XSD_STRING, + ParameterMode.IN); + call.setUsername(Aplaws.getAplawsConfig() + .getAutocatServiceUsername()); + call.setPassword(Aplaws.getAplawsConfig() + .getAutocatServicePassword()); + call.setReturnType(Constants.XSD_STRING); + LOG.debug("username/password="+call.getUsername()+"/"+call.getPassword()); + String result = (String) call.invoke(new Object[] { + buf.toString(), version }); + // parse the response from autocat service + SAXParser parser; + parser = SAXParserFactory.newInstance().newSAXParser(); + parser.parse(new InputSource(new StringReader(result)), + new SearchlightServiceHandler(terms)); + } else { + LOG.info("no metadata adapter for " + item); + } + } catch (Exception e) { + LOG.info("autocat service call failed", e); + throw new ServiceFailed(e); + } + return terms; + } + + // example autocat service response: + /*<searchlight:textminer + * xmlns:searchlight="http://www.cintra.com/MASmedia/Searchlight"> + * <searchlight:results> + * <searchlight:category-matches> + * <searchlight:category-match score="11"> + * <searchlight:category>Community Safety</searchlight:category> + * <searchlight:thesaurus-ref thesaurus="LGCS" version="0.01" id="182" /> + * <searchlight:thesaurus-ref thesaurus="LGSL" version="2.02" id="870" /> + * <searchlight:thesaurus-ref thesaurus="IPSV" version="2.00" id="6280" /> + * </searchlight:category-match> + * ... + */ + private static class SearchlightServiceHandler extends DefaultHandler { + + StringBuffer buffer; + String category = null; + String thesaurus = null; + String score = null; + Collection terms; + + public SearchlightServiceHandler(Collection terms) { + this.terms = terms; + } + + public void characters(char[] ch, int start, int len) + throws SAXException { + for (int i = 0; i < len; i++) { + buffer.append(ch[start + i]); + } + } + + public void startElement(String uri, String localName, String qName, + Attributes attributes) throws SAXException { + buffer = new StringBuffer(); + if ("searchlight:category-match".equals(qName)) { + score = attributes.getValue("score"); + } else if (category != null && score != null + && "searchlight:thesaurus-ref".equals(qName)) { + + thesaurus = attributes.getValue("thesaurus"); + if ("IPSV".equals(thesaurus)) { + LOG.debug("IPSV "+category); + Term t = findTerm(thesaurus, category); + if (t != null) { + terms.add(t); + LOG.debug("term = "+t); + } else { + LOG.debug("term not found"); + } } } - return null; } - + + public void endElement(String uri, String localName, String qName) + throws SAXException { + if ("searchlight:category".equals(qName)) { + category = buffer.toString(); + } else if ("searchlight:category-match".equals(qName)) { + category = null; score = null; thesaurus = null; + } else if ("searchlight:category-matches".equals(qName)) { + LOG.debug("terms autodetected "+terms); + } + } } + + public static class ServiceFailed extends RuntimeException { + public ServiceFailed(Throwable cause) { + super(cause); + } + } } Added: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoCategoryExtension.java =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoCategoryExtension.java 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoCategoryExtension.java 2006-08-25 18:17:50 UTC (rev 1295) @@ -0,0 +1,39 @@ +package com.arsdigita.aplaws.ui; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SimpleComponent; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.ui.authoring.ItemCategoryExtension; +import com.arsdigita.globalization.GlobalizedMessage; + +public class AutoCategoryExtension extends ItemCategoryExtension { + + public SimpleComponent[] getForm() { + SimpleComponent[] autocatForm = new SimpleComponent[1]; + autocatForm[0] = new AutoCategoryForm(); + return autocatForm; + } + + public SimpleComponent[] getSummary() { + SimpleComponent[] autocatLink = new SimpleComponent[1]; + autocatLink[0] = new AutoCatActionLink(); + return autocatLink; + } + + private class AutoCatActionLink extends ActionLink { + public AutoCatActionLink() { + super(new Label(new GlobalizedMessage("autocat.call.service","com.arsdigita.aplaws.AplawsResources"))); + addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + PageState state = e.getPageState(); + fireCompletionEvent(state); + } + }); + } + } +} Added: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoCategoryForm.java =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoCategoryForm.java 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoCategoryForm.java 2006-08-25 18:17:50 UTC (rev 1295) @@ -0,0 +1,112 @@ +package com.arsdigita.aplaws.ui; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; + +import com.arsdigita.aplaws.AutoCategorisation; +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SaveCancelSection; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.bebop.form.Hidden; +import com.arsdigita.bebop.form.MultipleSelect; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.parameters.ArrayParameter; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.categorization.Category; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ContentBundle; +import com.arsdigita.cms.ContentItem; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.london.terms.Term; +import com.arsdigita.persistence.OID; + +public class AutoCategoryForm extends Form { + + private MultipleSelect autoCatNames = new MultipleSelect("autoCatNames"); + private Hidden autoCatIDs = new Hidden(new ArrayParameter(new BigDecimalParameter("autoCatIDs"))); + private SaveCancelSection buttons = new SaveCancelSection(); + + public AutoCategoryForm() { + super("autocat", new BoxPanel(BoxPanel.VERTICAL)); + + add(new Label(new GlobalizedMessage("autocat.title","com.arsdigita.aplaws.AplawsResources"))); + autoCatNames.setReadOnly(); + autoCatNames.setDisabled(); + add(autoCatNames); + add(autoCatIDs); + add(buttons); + + addInitListener(new FormInitListener() { + public void init(FormSectionEvent e) + throws FormProcessException { + + PageState state = e.getPageState(); + try { + ContentItem item = CMS.getContext().getContentItem(); + Collection terms = AutoCategorisation.getAutoTerms(item); + Collection ids = new LinkedList(); + for (Iterator i=terms.iterator(); i.hasNext(); ) { + Term t = (Term) i.next(); + Category c = t.getModel(); + ids.add(c.getID()); + autoCatNames.addOption( new Option( c.getID().toString(), + c.getQualifiedName(">", true)), state); + } + autoCatIDs.setValue(state, + ids.toArray(new BigDecimal[ids.size()])); + } catch (AutoCategorisation.ServiceFailed sf) { + // XXX limit error msg length + autoCatNames.addOption( new Option( "0", + "FAILED: "+sf.getCause().getMessage()),state); + } + } + }); + + addProcessListener(new FormProcessListener() { + public void process(FormSectionEvent ev) + throws FormProcessException { + + PageState state = ev.getPageState(); + + ContentItem item = CMS.getContext().getContentItem(); + ContentBundle bundle = (ContentBundle)item.getParent(); + + BigDecimal[] ids = (BigDecimal[])autoCatIDs.getValue(state); + for (int i = 0 ; i < ids.length ; i++) { + Category cat = (Category) + DomainObjectFactory.newInstance( + new OID(Category.BASE_DATA_OBJECT_TYPE, + ids[i])); + // XXX mark it as auto + cat.addChild(bundle); + } + + fireCompletionEvent(state); + } + }); + + addSubmissionListener(new FormSubmissionListener() { + public void submitted(FormSectionEvent ev) + throws FormProcessException { + + PageState state = ev.getPageState(); + + if (buttons.getCancelButton().isSelected(state)) { + fireCompletionEvent(state); + throw new FormProcessException("cancelled"); + } + } + }); + } + +} Added: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoTerms.java =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoTerms.java 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/AutoTerms.java 2006-08-25 18:17:50 UTC (rev 1295) @@ -0,0 +1,53 @@ +package com.arsdigita.aplaws.ui; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.apache.log4j.Logger; + +import com.arsdigita.aplaws.AutoCategorisation; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SimpleComponent; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.cms.ContentItem; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.london.terms.Term; +import com.arsdigita.persistence.OID; +import com.arsdigita.xml.Element; + +public class AutoTerms extends SimpleComponent { + + private static final Logger LOG = Logger.getLogger(AutoTerms.class); + BigDecimalParameter itemIDparam = new BigDecimalParameter("itemID"); + + public void generateXML(PageState state, Element p) { + try { + BigDecimal itemID = (BigDecimal) state.getValue(itemIDparam); + ContentItem item = (ContentItem) DomainObjectFactory + .newInstance(new OID(ContentItem.BASE_DATA_OBJECT_TYPE, + itemID)); + + Collection terms = AutoCategorisation.getAutoTerms(item); + Set selected = new HashSet(); + BigDecimal sortKey = BigDecimal.valueOf(0); + final BigDecimal ONE = BigDecimal.valueOf(1); + for (Iterator i=terms.iterator(); i.hasNext(); ) { + Term term = (Term) i.next(); + TermWidget.generateTerm(p, term, selected, sortKey); + sortKey.add(ONE); + } + } catch (Exception e) { + LOG.info(e); + } + } + + public void register(Page p) { + super.register(p); + p.addGlobalStateParam(itemIDparam); + } + +} Added: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/CategorySubtree.java =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/CategorySubtree.java 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/CategorySubtree.java 2006-08-25 18:17:50 UTC (rev 1295) @@ -0,0 +1,35 @@ +package com.arsdigita.aplaws.ui; + +import java.math.BigDecimal; + +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SimpleComponent; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.categorization.Category; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.persistence.OID; +import com.arsdigita.xml.Element; + +/** + * Generate part of the category tree. Used by Assign Category authoring step. + * + * @author Alan Pevec + */ +public class CategorySubtree extends SimpleComponent { + + BigDecimalParameter catIDparam = new BigDecimalParameter("catID"); + + public void register(Page p) { + super.register(p); + p.addGlobalStateParam(catIDparam); + } + + public void generateXML(PageState state, Element p) { + Category root = (Category) DomainObjectFactory.newInstance(new OID( + Category.BASE_DATA_OBJECT_TYPE, (BigDecimal) state + .getValue(catIDparam))); + TermWidget.generateSubtree(p, root); + } + +} Modified: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/ItemCategoryPicker.java =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/ItemCategoryPicker.java 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/ItemCategoryPicker.java 2006-08-25 18:17:50 UTC (rev 1295) @@ -97,32 +97,26 @@ } private void lgclSelected(Domain domain, ContentBundle bundle) { - // adding processing or mapping from LGCL to APLAWS-NAV too - boolean lgclOverrideAnav = Aplaws.getAplawsConfig().getOverrideAnavFromLGCLMappings().booleanValue(); + List lgclTerms = getCurrentCategories(domain, bundle); Domain gcl = Domain.retrieve("GCL"); - Domain lgsl = Domain.retrieve("LGSL"); - Domain aplawsNav = Domain.retrieve("APLAWS-NAV"); - - List lgclTerms = getCurrentCategories(domain, bundle); - Collection lgslTerms = getRelatedTerms(lgclTerms, lgsl); Collection gclTerms = getRelatedTerms(lgclTerms, gcl); - Collection aplawsNavTerms = null; - if (lgclOverrideAnav) { - aplawsNavTerms = getRelatedTerms(lgclTerms, aplawsNav); - } - clearTerms(gcl, bundle); assignTerms(gclTerms, bundle); // The assignment below is removed to satisfy requirement 4.1, // use case 1 of the document "Metadata Improvements" version 1 // by Camden, dated 23/01/05. - + //Domain lgsl = Domain.retrieve("LGSL"); + //Collection lgslTerms = getRelatedTerms(lgclTerms, lgsl); //clearTerms(lgsl, bundle); //assignTerms(lgslTerms, bundle); - if (lgclOverrideAnav) { + // adding processing or mapping from LGCL to APLAWS-NAV too + boolean lgclOverrideAnav = Aplaws.getAplawsConfig().getOverrideAnavFromLGCLMappings().booleanValue(); + if (lgclOverrideAnav) { + Domain aplawsNav = Domain.retrieve("APLAWS-NAV"); + Collection aplawsNavTerms = getRelatedTerms(lgclTerms, aplawsNav); clearTerms(aplawsNav, bundle); assignTerms(aplawsNavTerms, bundle); } @@ -178,12 +172,13 @@ return current; } - protected List getCurrentTerms(Domain domain, + // TODO move out of UI code + public static Collection getCurrentTerms(Domain domain, ContentBundle bundle) { if (s_log.isDebugEnabled()) { s_log.debug("Getting terms from " + domain + " to " + bundle); } - List current = new LinkedList(); + Collection current = new LinkedList(); DomainCollection terms = domain.getTerms(); terms.addEqualsFilter("model.childObjects.id", bundle.getID()); terms.addPath("model.id"); @@ -213,7 +208,7 @@ terms.addEqualsFilter("model.parents.link.relationType", "related"); terms.addFilter("model.parents.id in :ids").set("ids", src); - List related = new LinkedList(); + Collection related = new LinkedList(); while (terms.next()) { if (s_log.isDebugEnabled()) { s_log.debug("Got term " + terms.getDomainObject()); Modified: trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/TermWidget.java =================================================================== --- trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/TermWidget.java 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/src/com/arsdigita/aplaws/ui/TermWidget.java 2006-08-25 18:17:50 UTC (rev 1295) @@ -28,6 +28,7 @@ import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.parameters.BigDecimalParameter; import com.arsdigita.categorization.Category; +import com.arsdigita.domain.DomainCollection; import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.persistence.DataCollection; import com.arsdigita.persistence.SessionManager; @@ -61,7 +62,7 @@ m_mode = mode; m_picker = picker; } - + protected String getType() { return "category"; } @@ -90,14 +91,10 @@ } } - DataCollection terms = SessionManager.getSession().retrieve - (Term.BASE_DATA_OBJECT_TYPE); - terms.addEqualsFilter("model.roTransParents.id", - domain.getModel().getID()); - terms.addEqualsFilter("model.parents.link.relationType", "child"); + // only root terms at first, the rest is loaded on-demand via AJAX + DomainCollection terms = domain.getRootTerms(); terms.addPath("model.parents.link.sortKey"); terms.addPath("model.parents.id"); - terms.addPath("domain.key"); // Pull out everything related to the category, otherwise @@ -112,39 +109,24 @@ terms.addPath("model.isAbstract"); terms.addPath("model.defaultAncestors"); - Map children = new HashMap(); + List roots = new LinkedList(); while (terms.next()) { - Term term = (Term) - DomainObjectFactory.newInstance(terms.getDataObject()); - BigDecimal parentID = (BigDecimal) terms.get("model.parents.id"); - - List childList = (List)children.get(parentID); - if (childList == null) { - childList = new LinkedList(); - children.put(parentID, childList); - } - - childList.add(new TermSortKeyPair + Term term = (Term) terms.getDomainObject(); + roots.add(new TermSortKeyPair (term,(BigDecimal)terms.get("model.parents.link.sortKey"))); } - // The top level category isn't a term, so has to be handled - // differently Element el = generateCategory(widget, domain.getModel(), ids, null); - List roots = (List) children.get(domain.getModel().getID()); - if (null != roots) { - Iterator i = roots.iterator(); - while (i.hasNext()) { - TermSortKeyPair pair = (TermSortKeyPair) i.next(); - Term term = pair.getTerm(); - BigDecimal sortKey = pair.getSortKey(); + for (Iterator i=roots.iterator(); i.hasNext(); ) { + TermSortKeyPair pair = (TermSortKeyPair) i.next(); + Term term = pair.getTerm(); + BigDecimal sortKey = pair.getSortKey(); - generateTerm(el, term, ids, sortKey, children); - } + generateRootTerm(el, term, ids, sortKey); } } - public Element generateCategory(Element parent, + public static Element generateCategory(Element parent, Category cat, Set selected, BigDecimal sortKey) { @@ -168,30 +150,91 @@ return el; } - public void generateTerm(Element parent, + public static Element generateTerm(Element parent, Term term, Set selected, - BigDecimal sortKey, - Map children) { + BigDecimal sortKey) { Category cat = term.getModel(); Element el = generateCategory(parent, cat, selected, sortKey); el.addAttribute("pid", term.getUniqueID().toString()); el.addAttribute("domain", term.getDomain().getKey()); + return el; + } + + private static void generateRootTerm(Element parent, + Term term, + Set selected, + BigDecimal sortKey) { + Element el = generateTerm(parent, term, selected, sortKey); + el.addAttribute("root","1"); + } + + public static void generateSubtree(Element parent, Category root) { + DataCollection terms = SessionManager.getSession().retrieve( + Term.BASE_DATA_OBJECT_TYPE); + terms.addEqualsFilter("model.roTransParents.id", root.getID()); + terms.addEqualsFilter("model.parents.link.relationType", "child"); - List c = (List)children.get(cat.getID()); + Map children = new HashMap(); + while (terms.next()) { + Term term = (Term) DomainObjectFactory.newInstance(terms + .getDataObject()); + BigDecimal parentID = (BigDecimal) terms.get("model.parents.id"); + + List childList = (List) children.get(parentID); + if (childList == null) { + childList = new LinkedList(); + children.put(parentID, childList); + } + + childList.add(new TermSortKeyPair(term, (BigDecimal) terms + .get("model.parents.link.sortKey"))); + } + + // XXX for isSelected + Set ids = new HashSet(); + + Element el = generateCategory(parent, root, ids, null); + el.addAttribute("fullname", root.getName()); + List roots = (List) children.get(root.getID()); + if (null != roots) { + Iterator i = roots.iterator(); + while (i.hasNext()) { + TermSortKeyPair pair = (TermSortKeyPair) i.next(); + Term term = pair.getTerm(); + BigDecimal sortKey = pair.getSortKey(); + + generateTermWithChildren(el, term, ids, sortKey, children); + } + } + } + + private static void generateTermWithChildren(Element parent, + Term term, + Set selected, + BigDecimal sortKey, + Map children) { + Category cat = term.getModel(); + Element el = generateCategory(parent, cat, selected, sortKey); + + el.addAttribute("pid", term.getUniqueID().toString()); + el.addAttribute("domain", term.getDomain().getKey()); + + List c = (List) children.get(cat.getID()); if (c != null) { Iterator i = c.iterator(); while (i.hasNext()) { TermSortKeyPair pair = (TermSortKeyPair) i.next(); Term child = pair.getTerm(); BigDecimal childSortKey = pair.getSortKey(); - generateTerm(el, child, selected, childSortKey, children); + generateTermWithChildren(el, child, selected, childSortKey, + children); } } } - private class TermSortKeyPair { + private static class TermSortKeyPair { private Term m_term; private BigDecimal m_sortKey; Added: trunk/ccm-ldn-aplaws/web/__ccm__/themes/aplaws/category-step.xsl =================================================================== --- trunk/ccm-ldn-aplaws/web/__ccm__/themes/aplaws/category-step.xsl 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/web/__ccm__/themes/aplaws/category-step.xsl 2006-08-25 18:17:50 UTC (rev 1295) @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<xsl:stylesheet + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:bebop="http://www.arsdigita.com/bebop/1.0" + xmlns:cms="http://www.arsdigita.com/cms/1.0" + xmlns:ui="http://www.arsdigita.com/ui/1.0" + xmlns:aplaws="http://www.arsdigita.com/aplaws/1.0" + version="1.0" exclude-result-prefixes="bebop cms ui aplaws xsl"> + + <xsl:import href="../../../../ROOT/__ccm__/static/cms/admin/category-step/category-step.xsl"/> + + <xsl:param name="theme-prefix" /> + + <xsl:template match="cms:emptyPage[@title='childCategories']"> + <xsl:apply-templates select="cms:category/cms:category" mode="cms:javascriptCat"> + <xsl:with-param name="expand" select="'none'"/> + </xsl:apply-templates> + </xsl:template> + + <xsl:template match="cms:emptyPage[@title='autoCategories']"> + <xsl:apply-templates select="cms:category" mode="cms:javascriptCat" /> + </xsl:template> + +</xsl:stylesheet> Modified: trunk/ccm-ldn-aplaws/web/__ccm__/themes/aplaws/content-section-admin.xsl =================================================================== --- trunk/ccm-ldn-aplaws/web/__ccm__/themes/aplaws/content-section-admin.xsl 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/web/__ccm__/themes/aplaws/content-section-admin.xsl 2006-08-25 18:17:50 UTC (rev 1295) @@ -9,6 +9,8 @@ <xsl:import href="../../../../ROOT/__ccm__/apps/content-section/xsl/admin.xsl"/> <xsl:import href="../../../../ROOT/packages/bebop/xsl/dcp.xsl"/> + + <xsl:import href="category-step.xsl"/> <xsl:param name="theme-prefix" /> Added: trunk/ccm-ldn-aplaws/web/packages/content-section/www/admin/auto-cat.jsp =================================================================== --- trunk/ccm-ldn-aplaws/web/packages/content-section/www/admin/auto-cat.jsp 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/web/packages/content-section/www/admin/auto-cat.jsp 2006-08-25 18:17:50 UTC (rev 1295) @@ -0,0 +1,13 @@ +<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" + xmlns:define="/WEB-INF/bebop-define.tld" + xmlns:show="/WEB-INF/bebop-show.tld" + version="1.2"> + + <define:page name="autoCategories" pageClass="com.arsdigita.cms.ui.authoring.EmptyPage" title="autoCategories" cache="true"> + + <define:component name="autoTerms" + classname="com.arsdigita.aplaws.ui.AutoTerms"/> + </define:page> + + <show:all/> +</jsp:root> Added: trunk/ccm-ldn-aplaws/web/packages/content-section/www/admin/load-cat.jsp =================================================================== --- trunk/ccm-ldn-aplaws/web/packages/content-section/www/admin/load-cat.jsp 2006-08-25 18:05:48 UTC (rev 1294) +++ trunk/ccm-ldn-aplaws/web/packages/content-section/www/admin/load-cat.jsp 2006-08-25 18:17:50 UTC (rev 1295) @@ -0,0 +1,13 @@ +<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" + xmlns:define="/WEB-INF/bebop-define.tld" + xmlns:show="/WEB-INF/bebop-show.tld" + version="1.2"> .. |
From: <ap...@vh...> - 2006-08-25 18:13:40
|
Author: apevec Date: 2006-08-25 20:05:48 +0200 (Fri, 25 Aug 2006) New Revision: 1294 Added: trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/EmptyPage.java trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryExtension.java trunk/ccm-cms/web/assets/category-step.js trunk/ccm-cms/web/assets/prototype.js Modified: trunk/ccm-cms/src/com/arsdigita/cms/ContentSectionConfig.java trunk/ccm-cms/src/com/arsdigita/cms/ContentSectionConfig_parameter.properties trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryStep.java trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategorySummary.java trunk/ccm-cms/web/__ccm__/static/cms/admin/category-step/category-step.xsl Log: category authoring step extension hook: in addition to the add form, extension actions can be added to category step by extending the default noop implementation ItemCategoryExtension Extension actions are shown as action links on the first (summary) page of category step, upon clicking them, extension form component is displayed. Modified: trunk/ccm-cms/src/com/arsdigita/cms/ContentSectionConfig.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ContentSectionConfig.java 2006-08-25 18:04:11 UTC (rev 1293) +++ trunk/ccm-cms/src/com/arsdigita/cms/ContentSectionConfig.java 2006-08-25 18:05:48 UTC (rev 1294) @@ -28,6 +28,7 @@ import com.arsdigita.cms.lifecycle.PublishLifecycleListener; import com.arsdigita.cms.publishToFile.PublishToFile; import com.arsdigita.cms.publishToFile.PublishToFileListener; +import com.arsdigita.cms.ui.authoring.ItemCategoryExtension; import com.arsdigita.cms.ui.authoring.ItemCategoryForm; import com.arsdigita.runtime.AbstractConfig; import com.arsdigita.util.parameter.BooleanParameter; @@ -104,6 +105,7 @@ private final Parameter m_defaultTaskAlerts; private final Parameter m_unpublishedNotFound; private final Parameter m_linksOnlyInSameSubsite; + private final Parameter m_categoryAuthoringExtension; /** * Do not instantiate this class directly. @@ -271,6 +273,12 @@ m_unpublishedNotFound = new BooleanParameter ("com.arsdigita.cms.unpublished_not_found", Parameter.REQUIRED, new Boolean(true)); + + m_categoryAuthoringExtension = new SpecificClassParameter + ("com.arsdigita.cms.category_authoring_extension", + Parameter.REQUIRED, + ItemCategoryExtension.class, + ItemCategoryExtension.class); register(m_templateRootPath); register(m_defaultItemTemplatePath); @@ -306,6 +314,7 @@ register(m_defaultTaskAlerts); register(m_unpublishedNotFound); register(m_linksOnlyInSameSubsite); + register(m_categoryAuthoringExtension); loadInfo(); } @@ -450,6 +459,10 @@ return ((Boolean) get(m_unpublishedNotFound)).booleanValue(); } + public final Class getCategoryAuthoringExtension() { + return (Class) get(m_categoryAuthoringExtension); + } + private class SpecificClassParameter extends ClassParameter { private Class m_requiredClass; Modified: trunk/ccm-cms/src/com/arsdigita/cms/ContentSectionConfig_parameter.properties =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ContentSectionConfig_parameter.properties 2006-08-25 18:04:11 UTC (rev 1293) +++ trunk/ccm-cms/src/com/arsdigita/cms/ContentSectionConfig_parameter.properties 2006-08-25 18:05:48 UTC (rev 1294) @@ -167,3 +167,9 @@ com.arsdigita.cms.browse_links_in_same_subsite_only.purpose=Links created through browse interfaces should only be within the same subsite com.arsdigita.cms.browse_links_in_same_subsite_only.example=false com.arsdigita.cms.browse_links_in_same_subsite_only.format=[boolean] + +com.arsdigita.cms.category_authoring_extension.title=Item category step extension hook +com.arsdigita.cms.category_authoring_extension.purpose=Subclass of ItemCategoryExtension which adds extension actions for the category authoring step +com.arsdigita.cms.category_authoring_extension.example=com.arsdigita.cms.ui.authoring.ItemCategoryExtension +com.arsdigita.cms.category_authoring_extension.format=[class] + Added: trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/EmptyPage.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/EmptyPage.java 2006-08-25 18:04:11 UTC (rev 1293) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/EmptyPage.java 2006-08-25 18:05:48 UTC (rev 1294) @@ -0,0 +1,28 @@ +package com.arsdigita.cms.ui.authoring; + +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.cms.CMS; +import com.arsdigita.xml.Document; +import com.arsdigita.xml.Element; + +/** + * Trivial extension of Bebop page. + * Can be used, for example, to deliver a part of the page to AJAX clients. + * + * @author Alan Pevec + */ +public class EmptyPage extends Page { + + public EmptyPage() { + super("", new SimpleContainer()); + } + + public void generateXML(PageState state, Document parent) { + Element page = parent.createRootElement("cms:emptyPage", CMS.CMS_XML_NS); + page.addAttribute("title", getTitle().getGlobalizedMessage().getKey()); + m_panel.generateXML(state, page); + } + +} Added: trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryExtension.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryExtension.java 2006-08-25 18:04:11 UTC (rev 1293) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryExtension.java 2006-08-25 18:05:48 UTC (rev 1294) @@ -0,0 +1,22 @@ +package com.arsdigita.cms.ui.authoring; + +import com.arsdigita.bebop.SimpleComponent; + +/** + * NOOP base implementation of category authoring step extension. + * Summary component returned by #getSummary() is show on category summary page, + * usually an ActionLink which activates the Form component returned by #getForm(). + * + * @author Alan Pevec + */ +public class ItemCategoryExtension { + + public SimpleComponent[] getSummary() { + return new SimpleComponent[0]; + } + + public SimpleComponent[] getForm() { + return new SimpleComponent[0]; + } + +} Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryStep.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryStep.java 2006-08-25 18:04:11 UTC (rev 1293) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryStep.java 2006-08-25 18:05:48 UTC (rev 1294) @@ -34,6 +34,7 @@ import com.arsdigita.cms.ContentSection; import com.arsdigita.cms.ItemSelectionModel; import com.arsdigita.cms.ui.authoring.AuthoringKitWizard; +import com.arsdigita.util.Assert; import com.arsdigita.util.Classes; import java.math.BigDecimal; @@ -46,6 +47,9 @@ private ItemCategorySummary m_summary; private SimpleComponent m_add; + private SimpleComponent[] m_extensionSummaries; + private SimpleComponent[] m_extensionForms; + private int m_extensionsCount; private BigDecimalParameter m_root; private StringParameter m_mode; @@ -57,12 +61,11 @@ m_mode = new StringParameter("mode"); m_summary = new ItemCategorySummary(); - m_summary.registerAction(ItemCategorySummary.ACTION_ADD, - new AddActionListener("plain")); + new AddActionListener("plain")); m_summary.registerAction(ItemCategorySummary.ACTION_ADD_JS, - new AddActionListener("javascript")); - + new AddActionListener("javascript")); + Class addForm = ContentSection.getConfig().getCategoryAuthoringAddForm(); m_add = (SimpleComponent) Classes.newInstance(addForm, @@ -70,7 +73,23 @@ StringParameter.class }, new Object[] { m_root, m_mode }); m_add.addCompletionListener(new ResetListener()); + + Class extensionClass = ContentSection.getConfig().getCategoryAuthoringExtension(); + ItemCategoryExtension extension = (ItemCategoryExtension) + Classes.newInstance(extensionClass); + m_extensionSummaries = extension.getSummary(); + m_extensionForms = extension.getForm(); + int nSummaries = m_extensionSummaries.length; + int nForms= m_extensionForms.length; + Assert.truth(nSummaries==nForms, "invalid CategoryStep extension"); + m_extensionsCount = nForms; + for (int i=0;i<m_extensionsCount;i++) { + m_extensionSummaries[i].addCompletionListener(new ExtensionListener(i)); + m_extensionForms[i].addCompletionListener(new ResetListener()); + add(m_extensionSummaries[i]); + add(m_extensionForms[i]); + } add(m_summary); add(m_add); } @@ -79,7 +98,9 @@ super.register(p); p.setVisibleDefault(m_add, false); - + for (int i=0;i<m_extensionsCount;i++) { + p.setVisibleDefault(m_extensionForms[i], false); + } p.addGlobalStateParam(m_root); p.addGlobalStateParam(m_mode); } @@ -89,7 +110,11 @@ state.setValue(m_mode, null); m_summary.setVisible(state, true); - m_add.setVisible(state, false); + m_add.setVisible(state, false); + for (int i=0;i<m_extensionsCount;i++) { + m_extensionSummaries[i].setVisible(state, true); + m_extensionForms[i].setVisible(state, false); + } } private class AddActionListener implements ActionListener { @@ -110,9 +135,13 @@ m_summary.setVisible(state, false); m_add.setVisible(state, true); + for (int i=0;i<m_extensionsCount;i++) { + m_extensionSummaries[i].setVisible(state, false); + m_extensionForms[i].setVisible(state, false); + } } } - + private class ResetListener implements ActionListener { public void actionPerformed(ActionEvent e) { PageState state = e.getPageState(); @@ -120,4 +149,21 @@ throw new RedirectSignal(state.toURL(), true); } } + + private class ExtensionListener implements ActionListener { + int extensionIndex; + public ExtensionListener(int i) { + extensionIndex = i; + } + public void actionPerformed(ActionEvent e) { + PageState state = e.getPageState(); + m_summary.setVisible(state, false); + m_add.setVisible(state, false); + for (int i=0;i<m_extensionsCount;i++) { + m_extensionSummaries[i].setVisible(state, false); + } + m_extensionForms[extensionIndex].setVisible(state, true); + } + } + } Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategorySummary.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategorySummary.java 2006-08-25 18:04:11 UTC (rev 1293) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategorySummary.java 2006-08-25 18:05:48 UTC (rev 1294) @@ -90,7 +90,7 @@ } } - private boolean canEdit(PageState state) { + protected boolean canEdit(PageState state) { SecurityManager sm = new SecurityManager( CMS.getContext().getContentSection()); return sm.canAccess(state.getRequest(), Modified: trunk/ccm-cms/web/__ccm__/static/cms/admin/category-step/category-step.xsl =================================================================== --- trunk/ccm-cms/web/__ccm__/static/cms/admin/category-step/category-step.xsl 2006-08-25 18:04:11 UTC (rev 1293) +++ trunk/ccm-cms/web/__ccm__/static/cms/admin/category-step/category-step.xsl 2006-08-25 18:05:48 UTC (rev 1294) @@ -89,101 +89,8 @@ </xsl:template> <xsl:template match="cms:categoryWidget" mode="cms:javascript"> - <script language="JavaScript"> - <![CDATA[ - <!-- Begin hiding - function catToggle(id) { - var elImgArray = getAllElementsByTypeAndID("img", "catTog"+id); - var elChildrenArray = getAllElementsByTypeAndID("div", "catCh"+id); - var elImg; - var elChildren; - for(i=0;i<elChildrenArray.length;i++){ - elImg = elImgArray[i]; - elChildren = elChildrenArray[i]; - - if (elChildren.style.display != "block") { - elChildren.style.display = "block"; - elImg.src = "/assets/action-delete.png"; - } else { - elChildren.style.display = "none"; - elImg.src = "/assets/action-add.png"; - } - } - return true; - } - function catSelect(id, name) { - var elWidget = document.getElementById("catWd"); - var elWidgetHidden = document.getElementById("catWdHd"); - var found = 0; - for (var i = 0 ; i < elWidget.options.length ; i++) { - if (elWidget.options[i].value == id) { - found = 1; - } - } - if (!found) { - var opt = new Option(name, id); - opt.onclick = "function() { catDeselect('" + id + "'); }"; - elWidget.options[elWidget.options.length] = opt; - - var optHidden = new Option(name, id, false, true); - elWidgetHidden.options[elWidgetHidden.options.length] = optHidden; - } - - var elLinkArray = getAllElementsByTypeAndID("a", "catLn"+id); - var elNameArray = getAllElementsByTypeAndID("span", "catNm"+id); - - var elLink; - var elName; - - for(i=0;i<elLinkArray.length;i++){ - elLink = elLinkArray[i]; - elName = elNameArray[i]; - elLink.style.display="none"; - elName.style.display="inline"; - } - return true; - } - function catDeselect() { - var elWidget = document.getElementById("catWd"); - var elWidgetHidden = document.getElementById("catWdHd"); - var idx = elWidget.selectedIndex; - if (idx != -1) { - var id = elWidget.options[idx].value; - - var elLinkArray = getAllElementsByTypeAndID("a", "catLn"+id); - var elNameArray = getAllElementsByTypeAndID("span", "catNm"+id); - - var elLink; - var elName; - - for(i=0;i<elLinkArray.length;i++){ - elLink = elLinkArray[i]; - elName = elNameArray[i]; - elLink.style.display="inline"; - elName.style.display="none"; - } - elWidget.options[idx] = null; - elWidgetHidden.options[idx] = null; - } - return true; - } - - function getAllElementsByTypeAndID(type, id){ - var a = new Array(); - var e; - var i = 0; - var elements = document.getElementsByTagName(type); - for (var i = 0; i < elements.length; i++) { - if(elements[i].id == id){ - a.push (elements[i]); - } - } - return a; - } - - // End hiding --> - ]]> - </script> + <script type="text/javascript" src="/assets/prototype.js"/> + <script type="text/javascript" src="/assets/category-step.js"/> <div> <xsl:apply-templates select="cms:category" mode="cms:javascriptCat"> <xsl:with-param name="expand" select="'block'"/> @@ -200,32 +107,30 @@ <xsl:param name="expand" select="'none'"/> <xsl:variable name="linkStyle"> <xsl:choose> - <xsl:when test="@isAbstract != '1' and @isSelected != '1'"> - <xsl:value-of select="'inline'"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="'none'"/> - </xsl:otherwise> + <xsl:when test="@isAbstract != '1' and @isSelected != '1'">inline</xsl:when> + <xsl:otherwise>none</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="nameStyle"> <xsl:choose> - <xsl:when test="@isAbstract != '1' and @isSelected != '1'"> - <xsl:value-of select="'none'"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="'inline'"/> - </xsl:otherwise> + <xsl:when test="@isAbstract != '1' and @isSelected != '1'">none</xsl:when> + <xsl:otherwise>inline</xsl:otherwise> </xsl:choose> </xsl:variable> + <xsl:variable name="toggle"> + <xsl:choose> + <xsl:when test="@root = '1'">catBranchToggle</xsl:when> + <xsl:otherwise>catToggle</xsl:otherwise> + </xsl:choose> + </xsl:variable> <div id="catSelf{@id}"> <xsl:choose> - <xsl:when test="count(cms:category) > 0 and $expand='none'"> - <a href="#" onClick="catToggle('{@id}');"><img id="catTog{@id}" src="/assets/action-add.png" width="14" height="14" border="0"/></a> + <xsl:when test="$expand='none' and (@root='1' or count(cms:category) > 0)"> + <a href="#" onClick="{$toggle}('{@id}');"><img id="catTog{@id}" src="/assets/action-add.png" width="14" height="14" border="0"/></a> </xsl:when> - <xsl:when test="count(cms:category) > 0 and $expand!='none'"> - <a href="#" onClick="catToggle('{@id}');"><img id="catTog{@id}" src="/assets/action-delete.png" width="14" height="14" border="0"/></a> + <xsl:when test="$expand!='none' and (@root='1' or count(cms:category) > 0)"> + <a href="#" onClick="{$toggle}('{@id}');"><img id="catTog{@id}" src="/assets/action-delete.png" width="14" height="14" border="0"/></a> </xsl:when> <xsl:otherwise> <img src="/assets/action-generic.png" width="14" height="14" border="0"/> Added: trunk/ccm-cms/web/assets/category-step.js =================================================================== --- trunk/ccm-cms/web/assets/category-step.js 2006-08-25 18:04:11 UTC (rev 1293) +++ trunk/ccm-cms/web/assets/category-step.js 2006-08-25 18:05:48 UTC (rev 1294) @@ -0,0 +1,72 @@ + function catBranchToggle(id) { + var elImg = $("catTog"+id); + var elChildren = $("catCh"+id); + + if (elChildren.style.display != "block") { + elChildren.innerHTML = 'loading...'; // discard the branch + elChildren.style.display = "block"; + // reload the branch + new Ajax.Updater('catCh'+id, 'load-cat.jsp', + {parameters:'catID='+id}); + elImg.src = "/assets/action-delete.png"; + // TODO check catWd, update selected catLn/catNm + // in case selected cats are in reloaded branch + } else { + elChildren.style.display = "none"; + elChildren.innerHTML = ''; // discard the branch + elImg.src = "/assets/action-add.png"; + } + return false; + } + function catToggle(id) { + var elImg = $("catTog"+id); + var elChildren = $("catCh"+id); + + if (elChildren.style.display != "block") { + elChildren.style.display = "block"; + elImg.src = "/assets/action-delete.png"; + } else { + elChildren.style.display = "none"; + elImg.src = "/assets/action-add.png"; + } + return false; + } + function catSelect(id, name) { + var elWidget = $("catWd"); + var elWidgetHidden = $("catWdHd"); + var found = 0; + for (var i = 0 ; i < elWidget.options.length ; i++) { + if (elWidget.options[i].value == id) { + found = 1; + } + } + if (!found) { + var opt = new Option(name, id); + opt.onclick = "function() { catDeselect('" + id + "'); }"; + elWidget.options[elWidget.options.length] = opt; + var optHidden = new Option(name, id, false, true); + elWidgetHidden.options[elWidgetHidden.options.length] = optHidden; + } + + var elLink = $("catLn"+id); + var elName = $("catNm"+id); + + elLink.style.display="none"; + elName.style.display="inline"; + return false; + } + function catDeselect() { + var elWidget = $("catWd"); + var elWidgetHidden = $("catWdHd"); + var idx = elWidget.selectedIndex; + if (idx != -1) { + var id = elWidget.options[idx].value; + var elLink = $("catLn"+id); + var elName = $("catNm"+id); + elLink.style.display="inline"; + elName.style.display="none"; + elWidget.options[idx] = null; + elWidgetHidden.options[idx] = null; + } + return false; + } Added: trunk/ccm-cms/web/assets/prototype.js =================================================================== --- trunk/ccm-cms/web/assets/prototype.js 2006-08-25 18:04:11 UTC (rev 1293) +++ trunk/ccm-cms/web/assets/prototype.js 2006-08-25 18:05:48 UTC (rev 1294) @@ -0,0 +1,1781 @@ +/* Prototype JavaScript framework, version 1.4.0 + * (c) 2005 Sam Stephenson <sa...@co...> + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://prototype.conio.net/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.4.0', + ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', + + emptyFunction: function() {}, + K: function(x) {return x} +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.inspect = function(object) { + try { + if (object == undefined) return 'undefined'; + if (object == null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } +} + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this; + return function(event) { + return __method.call(object, event || window.event); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + var digits = this.toString(16); + if (this < 16) return '0' + digits; + return digits; + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + } +}); + +var Try = { + these: function() { + var returnValue; + + for (var i = 0; i < arguments.length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(); + } finally { + this.currentlyExecuting = false; + } + } + } +} + +/*--------------------------------------------------------------------------*/ + +function $() { + var elements = new Array(); + + for (var i = 0; i < arguments.length; i++) { + var element = arguments[i]; + if (typeof element == 'string') + element = document.getElementById(element); + + if (arguments.length == 1) + return element; + + elements.push(element); + } + + return elements; +} +Object.extend(String.prototype, { + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(eval); + }, + + escapeHTML: function() { + var div = document.createElement('div'); + var text = document.createTextNode(this); + div.appendChild(text); + return div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; + }, + + toQueryParams: function() { + var pairs = this.match(/^\??(.*)$/)[1].split('&'); + return pairs.inject({}, function(params, pairString) { + var pair = pairString.split('='); + params[pair[0]] = pair[1]; + return params; + }); + }, + + toArray: function() { + return this.split(''); + }, + + camelize: function() { + var oStringList = this.split('-'); + if (oStringList.length == 1) return oStringList[0]; + + var camelizedString = this.indexOf('-') == 0 + ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) + : oStringList[0]; + + for (var i = 1, len = oStringList.length; i < len; i++) { + var s = oStringList[i]; + camelizedString += s.charAt(0).toUpperCase() + s.substring(1); + } + + return camelizedString; + }, + + inspect: function() { + return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; + } +}); + +String.prototype.parseQuery = String.prototype.toQueryParams; + +var $break = new Object(); +var $continue = new Object(); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + try { + iterator(value, index++); + } catch (e) { + if (e != $continue) throw e; + } + }); + } catch (e) { + if (e != $break) throw e; + } + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = true; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push(iterator(value, index)); + }); + return results; + }, + + detect: function (iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.collect(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (value >= (result || value)) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (value <= (result || value)) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.collect(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.collect(Prototype.K); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + iterator(value = collections.pluck(index)); + return value; + }); + }, + + inspect: function() { + return '#<Enumerable:' + this.toArray().inspect() + '>'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0; i < iterable.length; i++) + results.push(iterable[i]); + return results; + } +} + +Object.extend(Array.prototype, Enumerable); + +Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0; i < this.length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != undefined || value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0; i < this.length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + shift: function() { + var result = this[0]; + for (var i = 0; i < this.length - 1; i++) + this[i] = this[i + 1]; + this.length--; + return result; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } +}); +var Hash = { + _each: function(iterator) { + for (key in this) { + var value = this[key]; + if (typeof value == 'function') continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject($H(this), function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); .. |
From: <ap...@vh...> - 2006-08-25 18:11:43
|
Author: apevec Date: 2006-08-25 20:04:11 +0200 (Fri, 25 Aug 2006) New Revision: 1293 Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/item/Summary.java Log: show preferred category Modified: trunk/ccm-cms/src/com/arsdigita/cms/ui/item/Summary.java =================================================================== --- trunk/ccm-cms/src/com/arsdigita/cms/ui/item/Summary.java 2006-08-25 17:59:39 UTC (rev 1292) +++ trunk/ccm-cms/src/com/arsdigita/cms/ui/item/Summary.java 2006-08-25 18:04:11 UTC (rev 1293) @@ -18,6 +18,13 @@ */ package com.arsdigita.cms.ui.item; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.ServletException; + import com.arsdigita.bebop.PageState; import com.arsdigita.categorization.Category; import com.arsdigita.categorization.CategoryCollection; @@ -58,13 +65,6 @@ import com.arsdigita.workflow.simple.WorkflowTemplate; import com.arsdigita.xml.Element; -import java.net.URLEncoder; -import java.util.Date; -import java.util.Iterator; -import java.util.ArrayList; -import java.util.List; -import javax.servlet.ServletException; - /** * <p>This panel displays basic details about a content item such as * attributes and associations.</p> @@ -156,7 +156,7 @@ if (parentCategory.equals(subjectCategory)) { Element subjectElement = new Element("cms:subjectCategory",CMS.CMS_XML_NS); subjectElement.addAttribute("name",category.getName()); - subjectElement.setText(category.getQualifiedName(" -> ",true)); + subjectElement.setText(category.getPreferredQualifiedName(" -> ",true)); subjectsElement.addContent(subjectElement); } parents.close(); @@ -282,7 +282,7 @@ while (categories.next()) { Category category = categories.getCategory(); Element element = new Element("cms:category",CMS.CMS_XML_NS); - element.setText(category.getQualifiedName(" -> ",true)); + element.setText(category.getPreferredQualifiedName(" -> ",true)); categoryElement.addContent(element); } |