diff --git a/repository/src/main/java/org/orderofthebee/addons/support/tools/repo/jsconsole/AlfrescoScriptAPITernGet.java b/repository/src/main/java/org/orderofthebee/addons/support/tools/repo/jsconsole/AlfrescoScriptAPITernGet.java index 743cf7f..647b94b 100644 --- a/repository/src/main/java/org/orderofthebee/addons/support/tools/repo/jsconsole/AlfrescoScriptAPITernGet.java +++ b/repository/src/main/java/org/orderofthebee/addons/support/tools/repo/jsconsole/AlfrescoScriptAPITernGet.java @@ -26,11 +26,6 @@ * is now being licensed under the LGPL as part of the OOTBee Support Tools * addon. */ - - /** - * forked from https://github.com/AFaust/js-console - */ - package org.orderofthebee.addons.support.tools.repo.jsconsole; import java.lang.reflect.Method; @@ -39,7 +34,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -56,7 +50,6 @@ import org.alfresco.repo.jscript.BaseScopableProcessorExtension; import org.alfresco.repo.jscript.NativeMap; import org.alfresco.repo.jscript.Scopeable; -import org.alfresco.repo.jscript.ScriptLogger; import org.alfresco.repo.jscript.ScriptNode; import org.alfresco.repo.jscript.ScriptableHashMap; import org.alfresco.repo.jscript.ScriptableQNameMap; @@ -79,6 +72,8 @@ import org.alfresco.util.PropertyCheck; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContextAware; @@ -99,8 +94,8 @@ public class AlfrescoScriptAPITernGet extends DeclarativeWebScript implements InitializingBean { - private static final Collection> PRIMITIVE_NUMBER_CLASSES = Collections.unmodifiableList(Arrays.> asList(byte.class, - short.class, int.class, long.class, float.class, double.class)); + private static final Collection> PRIMITIVE_NUMBER_CLASSES = Collections + .unmodifiableList(Arrays.> asList(byte.class, short.class, int.class, long.class, float.class, double.class)); private static final Collection> CUTOFF_CLASSES = Collections.unmodifiableList(Arrays.> asList(Object.class, Scriptable.class, org.springframework.extensions.webscripts.processor.BaseProcessorExtension.class, @@ -110,11 +105,13 @@ public class AlfrescoScriptAPITernGet extends DeclarativeWebScript implements In ProcessorExtension.class, org.springframework.extensions.surf.core.processor.ProcessorExtension.class, Scopeable.class, ApplicationContextAware.class, InitializingBean.class, DisposableBean.class)); - private static final Collection INIT_METHOD_NAMES = Collections.unmodifiableSet(new HashSet(Arrays. asList( - "init", "register"))); + private static final Collection INIT_METHOD_NAMES = Collections + .unmodifiableSet(new HashSet(Arrays. asList("init", "register"))); private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new LocalVariableTableParameterNameDiscoverer(); + private static final Logger LOGGER = LoggerFactory.getLogger(AlfrescoScriptAPITernGet.class); + protected NamespaceService namespaceService; protected DictionaryService dictionaryService; @@ -147,7 +144,7 @@ public void afterPropertiesSet() /** * @param namespaceService - * the namespaceService to set + * the namespaceService to set */ public void setNamespaceService(final NamespaceService namespaceService) { @@ -156,7 +153,7 @@ public void setNamespaceService(final NamespaceService namespaceService) /** * @param dictionaryService - * the dictionaryService to set + * the dictionaryService to set */ public void setDictionaryService(final DictionaryService dictionaryService) { @@ -165,7 +162,7 @@ public void setDictionaryService(final DictionaryService dictionaryService) /** * @param scriptService - * the scriptService to set + * the scriptService to set */ public void setScriptService(final ScriptService scriptService) { @@ -174,7 +171,7 @@ public void setScriptService(final ScriptService scriptService) /** * @param personService - * the personService to set + * the personService to set */ public void setPersonService(final PersonService personService) { @@ -183,7 +180,7 @@ public void setPersonService(final PersonService personService) /** * @param serviceRegistry - * the serviceRegistry to set + * the serviceRegistry to set */ public void setServiceRegistry(final ServiceRegistry serviceRegistry) { @@ -192,7 +189,7 @@ public void setServiceRegistry(final ServiceRegistry serviceRegistry) /** * @param scriptProcessor - * the scriptProcessor to set + * the scriptProcessor to set */ public void setScriptProcessor(final BaseProcessor scriptProcessor) { @@ -201,7 +198,7 @@ public void setScriptProcessor(final BaseProcessor scriptProcessor) /** * @param properties - * the properties to set + * the properties to set */ public void setProperties(final Properties properties) { @@ -214,15 +211,15 @@ public void setProperties(final Properties properties) @Override protected Map executeImpl(final WebScriptRequest req, final Status status, final Cache cache) { - final Map model = new HashMap(); + final Map model = new HashMap<>(); this.prepareCoreScriptAPIJavaTypeDefinitions(model); - this.prepareCoreScriptAPIGlobalDefinitions(model); + final Map coreScriptModel = this.prepareCoreScriptAPIGlobalDefinitions(model); this.preparePropertyDefinitions(model); // TODO Process action definitions + parameters - this.prepareWebScriptAPIJavaTypeDefinitions(req, model); - this.prepareWebScriptAPIGlobalDefinitions(req, model); + this.prepareWebScriptAPIJavaTypeDefinitions(req, model, coreScriptModel); + this.prepareWebScriptAPIGlobalDefinitions(req, model, coreScriptModel); return model; } @@ -231,7 +228,7 @@ protected Map executeImpl(final WebScriptRequest req, final Stat * Prepares the type definitions for the core script API of Alfresco (common across all use cases) * * @param model - * the current web script model into which to insert the definitions + * the current web script model into which to insert the definitions */ protected void prepareCoreScriptAPIJavaTypeDefinitions(final Map model) { @@ -243,16 +240,19 @@ protected void prepareCoreScriptAPIJavaTypeDefinitions(final Map * Prepares the type definitions for the script API specific to Alfresco web scripts * * @param req - * the current web script request + * the current web script request * @param model - * the current web script model into which to insert the definitions + * the current web script model into which to insert the definitions + * @param coreScriptModel + * the core script API model in order to detect / avoid duplicate root object definitions */ - protected void prepareWebScriptAPIJavaTypeDefinitions(final WebScriptRequest req, final Map model) + protected void prepareWebScriptAPIJavaTypeDefinitions(final WebScriptRequest req, final Map model, + final Map coreScriptModel) { final ScriptDetails script = this.getExecuteScript(req.getContentType()); final Map scriptModel = this.createScriptParameters(req, null, script, Collections. emptyMap()); - this.removeCoreScriptAPIGlobalsFromWebScriptAPI(scriptModel); + this.removeCoreScriptAPIGlobalsFromWebScriptAPI(scriptModel, coreScriptModel); model.put("webScriptAPIJavaTypeDefinitions", this.prepareJavaTypeDefinitions(scriptModel)); } @@ -261,17 +261,21 @@ protected void prepareWebScriptAPIJavaTypeDefinitions(final WebScriptRequest req * Removes core script API globals from a script model specific to web script execution * * @param scriptModel - * the script model of a web script + * the script model of a web script + * @param coreScriptModel + * the core script API model in order to detect / avoid duplicate root object definitions */ - protected void removeCoreScriptAPIGlobalsFromWebScriptAPI(final Map scriptModel) + protected void removeCoreScriptAPIGlobalsFromWebScriptAPI(final Map scriptModel, + final Map coreScriptModel) { // avoid unnecessary overlap between web script and standard script API model - // remove well known types handled in core script API - final Collection keysToRemove = new HashSet(); + // remove identical key-value pairs handled by core script API + final Collection keysToRemove = new HashSet<>(); for (final Entry entry : scriptModel.entrySet()) { + final String key = entry.getKey(); final Object value = entry.getValue(); - if (value instanceof ScriptNode || value instanceof NodeRef || value instanceof ScriptLogger) + if (coreScriptModel.containsKey(key) && value.getClass().equals(scriptModel.get(key).getClass())) { keysToRemove.add(entry.getKey()); } @@ -282,15 +286,15 @@ protected void removeCoreScriptAPIGlobalsFromWebScriptAPI(final Map> prepareJavaTypeDefinitions(final Map model) { - final List> typeDefinitions = new ArrayList>(); + final List> typeDefinitions = new ArrayList<>(); - final Collection> classesToDescribe = new HashSet>(); - final Collection> classesDescribed = new HashSet>(); + final Collection> classesToDescribe = new HashSet<>(); + final Collection> classesDescribed = new HashSet<>(); for (final Entry modelEntry : model.entrySet()) { @@ -346,28 +350,34 @@ protected List> prepareJavaTypeDefinitions(final Map model) + protected Map prepareCoreScriptAPIGlobalDefinitions(final Map model) { final Map scriptModel = this.buildScriptAPIModel(); model.put("scriptAPIGlobalDefinitions", this.prepareGlobalDefinitions(scriptModel)); + + return scriptModel; } /** * Prepares the definitions for global / root scope objects found in the script API model specific to Alfresco web scripts * * @param req - * the current web script request + * the current web script request * @param model - * the model into which to insert the global definitions + * the model into which to insert the global definitions + * @param coreScriptModel + * the core script API model in order to detect / avoid duplicate root object definitions */ - protected void prepareWebScriptAPIGlobalDefinitions(final WebScriptRequest req, final Map model) + protected void prepareWebScriptAPIGlobalDefinitions(final WebScriptRequest req, final Map model, + final Map coreScriptModel) { final ScriptDetails script = this.getExecuteScript(req.getContentType()); final Map scriptModel = this.createScriptParameters(req, null, script, Collections. emptyMap()); - this.removeCoreScriptAPIGlobalsFromWebScriptAPI(scriptModel); + this.removeCoreScriptAPIGlobalsFromWebScriptAPI(scriptModel, coreScriptModel); model.put("webScriptAPIGlobalDefinitions", this.prepareGlobalDefinitions(scriptModel)); } @@ -376,12 +386,12 @@ protected void prepareWebScriptAPIGlobalDefinitions(final WebScriptRequest req, * Prepares the global definitions for Java objects found in a specific model. * * @param model - * the model containing objects exposed to scripts + * the model containing objects exposed to scripts * @return the list of models for each global value */ protected List> prepareGlobalDefinitions(final Map model) { - final List> globalDefinitions = new ArrayList>(); + final List> globalDefinitions = new ArrayList<>(); for (final Entry modelEntry : model.entrySet()) { @@ -400,7 +410,7 @@ protected List> prepareGlobalDefinitions(final Map globalDefinition = new HashMap(); + final Map globalDefinition = new HashMap<>(); globalDefinition.put("name", globalEntry.getKey()); final Object value = globalEntry.getValue(); @@ -449,7 +459,7 @@ protected List> prepareGlobalDefinitions(final Map> fillClassTypeDefinition(final Class cls, final Map typeDefinition) { - final Collection> relatedClasses = new HashSet>(); + final Collection> relatedClasses = new HashSet<>(); final String clsName = cls.getName(); final String commonPrefix = "type." + clsName; @@ -474,12 +484,7 @@ protected Collection> fillClassTypeDefinition(final Class cls, final typeDefinition.put("doc", ternDoc); } - String ternUrl = this.properties.getProperty(commonPrefix + ".ternUrl"); - if ((ternUrl == null || ternUrl.isEmpty()) && clsName.startsWith("org.alfresco.")) - { - ternUrl = "http://dev.alfresco.com/resource/docs/java/" + clsName.replace('.', '/') + ".html"; - } - + final String ternUrl = this.properties.getProperty(commonPrefix + ".ternUrl"); if (ternUrl != null && !ternUrl.isEmpty()) { typeDefinition.put("url", ternUrl); @@ -588,13 +593,13 @@ else if (methodName.matches("^set[A-Z].*$") && method.getParameterTypes().length protected List collectDocumentableMethods(final Class cls) { // collect classes in hierarchy from base to special - final List> classHierarchy = new LinkedList>(); + final List> classHierarchy = new LinkedList<>(); Class curCls = cls; while (curCls != null) { classHierarchy.add(0, curCls); - final Collection> interfaces = new HashSet>(Arrays.asList(curCls.getInterfaces())); + final Collection> interfaces = new HashSet<>(Arrays.asList(curCls.getInterfaces())); // interfaces are the collection of superclasses for an interface if (curCls.isInterface()) @@ -634,7 +639,7 @@ protected List collectDocumentableMethods(final Class cls) } // collect declared public methods (other than cls.getMethods we don't want overriden methods, only initial implementations) - final Map>>, Method> methodsByNameAndParameterTypes = new HashMap>>, Method>(); + final Map>>, Method> methodsByNameAndParameterTypes = new HashMap<>(); while (!classHierarchy.isEmpty()) { curCls = classHierarchy.remove(0); @@ -645,8 +650,7 @@ protected List collectDocumentableMethods(final Class cls) if (Modifier.isPublic(declaredMethod.getModifiers()) && !Modifier.isStatic(declaredMethod.getModifiers())) { - final Pair>> key = new Pair>>(methodName, Arrays.asList(declaredMethod - .getParameterTypes())); + final Pair>> key = new Pair<>(methodName, Arrays.asList(declaredMethod.getParameterTypes())); if (!methodsByNameAndParameterTypes.containsKey(key)) { methodsByNameAndParameterTypes.put(key, declaredMethod); @@ -664,10 +668,10 @@ protected List collectDocumentableMethods(final Class cls) { // ignore potential initialization setters / methods final String methodName = method.getName(); - if ((BaseProcessorExtension.class.isAssignableFrom(method.getDeclaringClass()) || WebScript.class.isAssignableFrom(method - .getDeclaringClass())) - && (INIT_METHOD_NAMES.contains(methodName) || methodName.matches("^[sg]et[A-Z].+Service$") || (methodName - .matches("^set[A-Z].+$") && method.getParameterTypes().length == 1))) + if ((BaseProcessorExtension.class.isAssignableFrom(method.getDeclaringClass()) + || WebScript.class.isAssignableFrom(method.getDeclaringClass())) + && (INIT_METHOD_NAMES.contains(methodName) || methodName.matches("^[sg]et[A-Z].+Service$") + || (methodName.matches("^set[A-Z].+$") && method.getParameterTypes().length == 1))) { // skip continue; @@ -677,33 +681,23 @@ protected List collectDocumentableMethods(final Class cls) } } - Collections.sort(documentableMethods, new Comparator() - { + Collections.sort(documentableMethods, (a, b) -> { + final String aName = a.getName(); + final String bName = b.getName(); - /** - * - * {@inheritDoc} - */ - @Override - public int compare(final Method a, final Method b) + int result = aName.compareTo(bName); + if (result == 0) { - final String aName = a.getName(); - final String bName = b.getName(); + final int aArgLength = a.getParameterTypes().length; + final int bArgLength = b.getParameterTypes().length; - int result = aName.compareTo(bName); - if (result == 0) + if (aArgLength != bArgLength) { - final int aArgLength = a.getParameterTypes().length; - final int bArgLength = b.getParameterTypes().length; - - if (aArgLength != bArgLength) - { - result = aArgLength - bArgLength; - } + result = aArgLength - bArgLength; } - - return result; } + + return result; }); return documentableMethods; @@ -731,7 +725,7 @@ protected Map buildClassMethodMemberDefinition(final Class cl if (skip == null || skip.isEmpty() || !Boolean.parseBoolean(skip)) { - memberDefinition = new HashMap(); + memberDefinition = new HashMap<>(); effectiveReturnType = this.determineEffectiveType(realReturnType, effectiveReturnType, methodPrefix); final Class returnType = this.determineType(effectiveReturnType, relatedClasses); @@ -786,7 +780,7 @@ protected Map buildClassPropertyMemberDefinition(final Class if (skip == null || skip.isEmpty() || !Boolean.parseBoolean(skip)) { - memberDefinition = new HashMap(); + memberDefinition = new HashMap<>(); effectiveReturnType = this.determineEffectiveType(realReturnType, effectiveReturnType, propertyPrefix); final Class returnType = this.determineType(effectiveReturnType, relatedClasses); @@ -876,7 +870,7 @@ protected Class determineEffectiveType(final Class realType, final Class buildScriptAPIModel() * (authentication / tenant) * * @param model - * the model into which to insert the definitions + * the model into which to insert the definitions */ protected void preparePropertyDefinitions(final Map model) { @@ -1164,7 +1155,7 @@ protected void preparePropertyDefinitions(final Map model) model.put("taskProperties", this.buildPropertyDefinitions(taskTypes, taskAspects)); // though task types could technically be used for nodes (task derives from cm:content) they rarely are - final Collection nodeTypes = new HashSet(this.dictionaryService.getAllTypes()); + final Collection nodeTypes = new HashSet<>(this.dictionaryService.getAllTypes()); nodeTypes.removeAll(nodeTypes); final Collection nodeAspects = this.dictionaryService.getAllAspects(); @@ -1175,7 +1166,7 @@ protected List buildPropertyDefinitions(final Collection propertyDefinitions = new ArrayList(); - final Collection allClasses = new HashSet(); + final Collection allClasses = new HashSet<>(); allClasses.addAll(types); allClasses.addAll(aspects); @@ -1192,10 +1183,11 @@ protected List buildPropertyDefinitions(final QName cls) final ClassDefinition classDefinition = this.dictionaryService.getClass(cls); final Map properties = classDefinition.getProperties(); - final Map parentProperties = classDefinition.getParentName() != null ? classDefinition - .getParentClassDefinition().getProperties() : Collections. emptyMap(); + final Map parentProperties = classDefinition.getParentName() != null + ? classDefinition.getParentClassDefinition().getProperties() + : Collections. emptyMap(); - final List propertyDefinitions = new ArrayList(); + final List propertyDefinitions = new ArrayList<>(); for (final Entry propertyEntry : properties.entrySet()) { @@ -1210,7 +1202,7 @@ protected List buildPropertyDefinitions(final QName cls) protected Collection collectTaskAspects(final Collection taskTypes) { - final Collection taskAspects = new HashSet(); + final Collection taskAspects = new HashSet<>(); for (final QName taskType : taskTypes) { final TypeDefinition type = this.dictionaryService.getType(taskType); diff --git a/repository/src/main/resources/alfresco/module/ootbee-support-tools-repo/jsconsole-tern.properties b/repository/src/main/resources/alfresco/module/ootbee-support-tools-repo/jsconsole-tern.properties index b6e765d..34a8d62 100644 --- a/repository/src/main/resources/alfresco/module/ootbee-support-tools-repo/jsconsole-tern.properties +++ b/repository/src/main/resources/alfresco/module/ootbee-support-tools-repo/jsconsole-tern.properties @@ -6,10 +6,13 @@ global.url.typeClassName=org.springframework.extensions.webscripts.URLModel # Scriptable JMX API is just too nasty global.jmx.skip=true +# Java numeric/boolean values are auto-converted when return from methods type.java.lang.String.ternName=JavaString type.java.lang.Character.ternName=JavaCharacter type.java.lang.Number.ternName=JavaNumber +type.java.lang.Number.returnTypeTernName=number type.java.lang.Boolean.ternName=JavaBoolean +type.java.lang.Boolean.returnTypeTernName=bool type.java.util.Date.ternName=JavaDate type.java.util.Map.ternName=JavaMap type.java.util.List.ternName=JavaList @@ -39,6 +42,7 @@ type.java.lang.Object.notifyAll.skip=true type.java.lang.Object.wait.skip=true type.java.lang.Object.toString.skip=true type.java.lang.Enum.declaringClass.skip=true +type.java.lang.Comparable.compareTo.skip=true type.java.util.Date.toInstant.skip=true type.org.springframework.extensions.webscripts.WebScript.execute.skip=true @@ -64,6 +68,12 @@ type.org.alfresco.repo.jscript.Person.getImmutableProperties.in.String.out.Scrip type.org.alfresco.repo.workflow.jscript.JscriptWorkflowTask.properties.typeTernName=TaskProperties type.org.alfresco.repo.jscript.Search.queryResultSet.in.Object.out.Scriptable.typeTernName=SearchResultSetMeta +# native char is handled as a number +type.java.lang.String.charAt.out.char.in.int.returnTypeTernName=number +type.java.lang.String.toCharArray.out.char[].returnTypeTernName=number + +type.java.lang.String.chars.skip=true +type.java.lang.String.codePoints.skip=true type.java.lang.String.getChars.skip=true type.java.lang.String.getBytes.skip=true type.java.lang.String.contentEquals.skip=true diff --git a/share/src/main/resources/META-INF/resources/components/ootbee-support-tools/codemirror/addon/hint/show-hint.css b/share/src/main/resources/META-INF/resources/components/ootbee-support-tools/codemirror/addon/hint/show-hint.css index 924e638..432725a 100644 --- a/share/src/main/resources/META-INF/resources/components/ootbee-support-tools/codemirror/addon/hint/show-hint.css +++ b/share/src/main/resources/META-INF/resources/components/ootbee-support-tools/codemirror/addon/hint/show-hint.css @@ -25,7 +25,6 @@ margin: 0; padding: 0 4px; border-radius: 2px; - max-width: 19em; overflow: hidden; white-space: pre; color: black; diff --git a/share/src/main/resources/alfresco/site-webscripts/org/orderofthebee/support-tools/console/support-tools/ootbee-jsconsole.get.head.ftl b/share/src/main/resources/alfresco/site-webscripts/org/orderofthebee/support-tools/console/support-tools/ootbee-jsconsole.get.head.ftl index efb65cc..d894a97 100644 --- a/share/src/main/resources/alfresco/site-webscripts/org/orderofthebee/support-tools/console/support-tools/ootbee-jsconsole.get.head.ftl +++ b/share/src/main/resources/alfresco/site-webscripts/org/orderofthebee/support-tools/console/support-tools/ootbee-jsconsole.get.head.ftl @@ -123,11 +123,8 @@ addon. <@script type="text/javascript" src="${page.url.context}/res/components/ootbee-support-tools/codemirror/addon/tern/tern-hover.js"> <@script type="text/javascript" src="${page.url.context}/res/components/ootbee-support-tools/codemirror/addon/tern/tern-hyperlink.js"> - + <@script type="text/javascript" src="${page.url.context}/res/components/ootbee-support-tools/codemirror/addon/tern/defs/ecma5.json.js"> -<@script type="text/javascript" src="${page.url.context}/res/components/ootbee-support-tools/codemirror/addon/tern/defs/alfresco-json.js"> -<@script type="text/javascript" src="${page.url.context}/res/components/ootbee-support-tools/codemirror/addon/tern/defs/alfresco-webscripts-tern.js"> -<@script type="text/javascript" src="${page.url.context}/res/components/ootbee-support-tools/codemirror/addon/tern/defs/alfresco-batchprocessing-tern.js"> <@script type="text/javascript" src="${page.url.context}/res/components/ootbee-support-tools/codemirror/addon/tern/defs/alfresco-json-dynamic.js">