From d24a815b79101349031600c071fa3f15e6304006 Mon Sep 17 00:00:00 2001 From: Kevin Roast Date: Wed, 9 Aug 2006 12:51:42 +0000 Subject: [PATCH] . JavaScript API improvements . Template API improvements . Fixed a couple more UTF-8 code file warnings when compiling the source git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3473 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../executer/ContentMetadataExtracter.java | 4 +- .../HtmlParserContentTransformerTest.java | 2 - .../java/org/alfresco/repo/jscript/Node.java | 110 ++++++++++++------ .../org/alfresco/repo/jscript/Search.java | 34 ++++++ .../repo/template/NamePathResultsMap.java | 2 +- .../repo/template/NodeSearchResultsMap.java | 62 ++++++++++ .../repo/template/XPathResultsMap.java | 2 +- .../service/cmr/repository/TemplateNode.java | 9 ++ 8 files changed, 183 insertions(+), 42 deletions(-) create mode 100644 source/java/org/alfresco/repo/template/NodeSearchResultsMap.java diff --git a/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java b/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java index 66d29848e4..04118eebb8 100644 --- a/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java +++ b/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Jesper Steen Møller + * Copyright (C) 2005 Jesper Steen Møller * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a @@ -43,7 +43,7 @@ import org.alfresco.service.namespace.QName; * otherwise they are left as is.
* This may change if the action gets parameterized in future. * - * @author Jesper Steen Møller + * @author Jesper Steen Møller */ public class ContentMetadataExtracter extends ActionExecuterAbstractBase { diff --git a/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java index 779ad2dd2d..8ae227fd17 100644 --- a/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java @@ -25,8 +25,6 @@ import org.alfresco.repo.content.MimetypeMap; */ public class HtmlParserContentTransformerTest extends AbstractContentTransformerTest { - private static final String SOME_CONTENT = "azAz10!£$%^&*()\t\r\n"; - private ContentTransformer transformer; @Override diff --git a/source/java/org/alfresco/repo/jscript/Node.java b/source/java/org/alfresco/repo/jscript/Node.java index 5644a16d51..f9b4824997 100644 --- a/source/java/org/alfresco/repo/jscript/Node.java +++ b/source/java/org/alfresco/repo/jscript/Node.java @@ -21,6 +21,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -405,33 +406,8 @@ public final class Node implements Serializable, Scopeable { Serializable propValue = props.get(qname); - // perform conversions from Java objects to JavaScript scriptable instances - if (propValue instanceof NodeRef) - { - // NodeRef object properties are converted to new Node objects - // so they can be used as objects within a template - propValue = new Node( - ((NodeRef)propValue), this.services, this.imageResolver, this.scope); - } - else if (propValue instanceof ContentData) - { - // ContentData object properties are converted to ScriptContentData objects - // so the content and other properties of those objects can be accessed - propValue = new ScriptContentData((ContentData)propValue, qname); - } - else if (propValue instanceof Date) - { - // convert Date to JavaScript native Date object - // call the "Date" constructor on the root scope object - passing in the millisecond - // value from the Java date - this will construct a JavaScript Date with the same value - Date date = (Date)propValue; - Object val = ScriptRuntime.newObject( - Context.getCurrentContext(), this.scope, "Date", new Object[] {date.getTime()}); - propValue = (Serializable)val; - } - // simple numbers and strings are handled automatically by Rhino - - this.properties.put(qname.toString(), propValue); + // perform the conversion to a script safe value and store + this.properties.put(qname.toString(), convertValueForScript(qname, propValue)); } } @@ -924,7 +900,7 @@ public final class Node implements Serializable, Scopeable Serializable value = (Serializable)this.properties.get(key); // perform the conversion from script wrapper object to repo serializable values - value = convertValue(value); + value = convertValueForRepo(value); props.put(createQName(key), value); } @@ -939,9 +915,13 @@ public final class Node implements Serializable, Scopeable * * @return valid repo value */ - private static Serializable convertValue(Serializable value) + private static Serializable convertValueForRepo(Serializable value) { - if (value instanceof Node) + if (value == null) + { + return null; + } + else if (value instanceof Node) { // convert back to NodeRef value = ((Node)value).getNodeRef(); @@ -955,7 +935,7 @@ public final class Node implements Serializable, Scopeable { // unwrap a Java object from a JavaScript wrapper // recursively call this method to convert the unwrapped value - value = convertValue((Serializable)((Wrapper)value).unwrap()); + value = convertValueForRepo((Serializable)((Wrapper)value).unwrap()); } else if (value instanceof ScriptableObject) { @@ -979,7 +959,7 @@ public final class Node implements Serializable, Scopeable // get the value out for the specified key Serializable val = (Serializable)values.get((Integer)propId, values); // recursively call this method to convert the value - propValues.add(convertValue(val)); + propValues.add(convertValueForRepo(val)); } } value = (Serializable)propValues; @@ -997,6 +977,61 @@ public final class Node implements Serializable, Scopeable return value; } + /** + * Convert an object from any repository serialized value to a valid script object. + * This includes converting Collection multi-value properties into JavaScript Array objects. + * + * @param qname QName of the property value for conversion + * @param value Property value + * + * @return Value safe for scripting usage + */ + private Serializable convertValueForScript(QName qname, Serializable value) + { + // perform conversions from Java objects to JavaScript scriptable instances + if (value == null) + { + return null; + } + else if (value instanceof NodeRef) + { + // NodeRef object properties are converted to new Node objects + // so they can be used as objects within a template + value = new Node(((NodeRef)value), this.services, this.imageResolver, this.scope); + } + else if (value instanceof ContentData) + { + // ContentData object properties are converted to ScriptContentData objects + // so the content and other properties of those objects can be accessed + value = new ScriptContentData((ContentData)value, qname); + } + else if (value instanceof Date) + { + // convert Date to JavaScript native Date object + // call the "Date" constructor on the root scope object - passing in the millisecond + // value from the Java date - this will construct a JavaScript Date with the same value + Date date = (Date)value; + Object val = ScriptRuntime.newObject( + Context.getCurrentContext(), this.scope, "Date", new Object[] {date.getTime()}); + value = (Serializable)val; + } + else if (value instanceof Collection) + { + // recursively convert each value in the collection + Collection collection = (Collection)value; + Serializable[] array = new Serializable[collection.size()]; + int index = 0; + for (Serializable obj : collection) + { + array[index++] = convertValueForScript(qname, obj); + } + value = array; + } + // simple numbers and strings are wrapped automatically by Rhino + + return value; + } + /** * Re-sets the type of the node. Can be called in order specialise a node to a sub-type. * @@ -1300,7 +1335,7 @@ public final class Node implements Serializable, Scopeable { // get the value out for the specified key - make sure it is Serializable Object value = props.get((String)propId, props); - value = convertValue((Serializable)value); + value = convertValueForRepo((Serializable)value); aspectProps.put(createQName((String)propId), (Serializable)value); } } @@ -1502,19 +1537,22 @@ public final class Node implements Serializable, Scopeable if (reader != null) { // Copy the content node to a new node + String copyName = TransformActionExecuter.transformName( + this.services.getMimetypeService(), getName(), mimetype); NodeRef copyNodeRef = this.services.getCopyService().copy( this.nodeRef, destination, ContentModel.ASSOC_CONTAINS, - getPrimaryParentAssoc().getQName(), + QName.createQName( + ContentModel.PROP_CONTENT.getNamespaceURI(), + QName.createValidLocalName(copyName)), false); // modify the name of the copy to reflect the new mimetype this.nodeService.setProperty( copyNodeRef, ContentModel.PROP_NAME, - TransformActionExecuter.transformName( - this.services.getMimetypeService(), getName(), mimetype)); + copyName); // get the writer and set it up ContentWriter writer = contentService.getWriter(copyNodeRef, ContentModel.PROP_CONTENT, true); diff --git a/source/java/org/alfresco/repo/jscript/Search.java b/source/java/org/alfresco/repo/jscript/Search.java index adde07b567..79ee477ae5 100644 --- a/source/java/org/alfresco/repo/jscript/Search.java +++ b/source/java/org/alfresco/repo/jscript/Search.java @@ -80,6 +80,40 @@ public final class Search implements Scopeable this.scope = scope; } + /** + * Find a single Node by the Node reference + * + * @param ref The NodeRef of the Node to find + * + * @return the Node if found or null if failed to find + */ + public Node findNode(NodeRef ref) + { + return findNode(ref.toString()); + } + + /** + * Find a single Node by the Node reference + * + * @param ref The fully qualified NodeRef in String format + * + * @return the Node if found or null if failed to find + */ + public Node findNode(String ref) + { + String query = ref.replace(":", "\\:"); + query = query.replace("/", "\\/"); + Node[] result = query("ID:" + query); + if (result.length == 1) + { + return result[0]; + } + else + { + return null; + } + } + /** * Execute a Lucene search * diff --git a/source/java/org/alfresco/repo/template/NamePathResultsMap.java b/source/java/org/alfresco/repo/template/NamePathResultsMap.java index 3cf8a77267..9641da39af 100644 --- a/source/java/org/alfresco/repo/template/NamePathResultsMap.java +++ b/source/java/org/alfresco/repo/template/NamePathResultsMap.java @@ -28,7 +28,7 @@ import org.alfresco.service.cmr.repository.TemplateNode; * * @author Kevin Roast */ -public final class NamePathResultsMap extends BasePathResultsMap +public class NamePathResultsMap extends BasePathResultsMap { /** * Constructor diff --git a/source/java/org/alfresco/repo/template/NodeSearchResultsMap.java b/source/java/org/alfresco/repo/template/NodeSearchResultsMap.java new file mode 100644 index 0000000000..2ae5213683 --- /dev/null +++ b/source/java/org/alfresco/repo/template/NodeSearchResultsMap.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.repo.template; + +import java.util.List; + +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.TemplateNode; + +/** + * Provides functionality to execute a Lucene search for a single node by NodeRef. + * + * @author Kevin Roast + */ +public class NodeSearchResultsMap extends BaseSearchResultsMap +{ + /** + * Constructor + * + * @param parent The parent TemplateNode to execute searches from + * @param services The ServiceRegistry to use + */ + public NodeSearchResultsMap(TemplateNode parent, ServiceRegistry services) + { + super(parent, services); + } + + /** + * @see org.alfresco.repo.template.BaseTemplateMap#get(java.lang.Object) + */ + public Object get(Object key) + { + TemplateNode result = null; + if (key != null) + { + String ref = key.toString().replace(":", "\\:"); + ref = ref.replace("/", "\\/"); + + List results = query(ref); + + if (results.size() == 1) + { + result = results.get(0); + } + } + return result; + } +} diff --git a/source/java/org/alfresco/repo/template/XPathResultsMap.java b/source/java/org/alfresco/repo/template/XPathResultsMap.java index dcc6a23b47..dc0ae7210e 100644 --- a/source/java/org/alfresco/repo/template/XPathResultsMap.java +++ b/source/java/org/alfresco/repo/template/XPathResultsMap.java @@ -25,7 +25,7 @@ import org.alfresco.service.cmr.repository.TemplateNode; * * @author Kevin Roast */ -public final class XPathResultsMap extends BasePathResultsMap +public class XPathResultsMap extends BasePathResultsMap { /** * Constructor diff --git a/source/java/org/alfresco/service/cmr/repository/TemplateNode.java b/source/java/org/alfresco/service/cmr/repository/TemplateNode.java index c9b64e52a4..5b76de0058 100644 --- a/source/java/org/alfresco/service/cmr/repository/TemplateNode.java +++ b/source/java/org/alfresco/service/cmr/repository/TemplateNode.java @@ -30,6 +30,7 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.template.LuceneSearchResultsMap; import org.alfresco.repo.template.NamePathResultsMap; +import org.alfresco.repo.template.NodeSearchResultsMap; import org.alfresco.repo.template.SavedSearchResultsMap; import org.alfresco.repo.template.XPathResultsMap; import org.alfresco.service.ServiceRegistry; @@ -235,6 +236,14 @@ public final class TemplateNode implements Serializable return new LuceneSearchResultsMap(this, this.services); } + /** + * @return A map capable of returning a TemplateNode for a single specified NodeRef reference. + */ + public Map getNodeByReference() + { + return new NodeSearchResultsMap(this, this.services); + } + /** * @return The associations for this Node. As a Map of assoc name to a List of TemplateNodes. */