diff options
author | Leif Åstrand <leif@vaadin.com> | 2014-02-12 15:49:31 +0200 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2014-02-12 15:49:49 +0200 |
commit | 42f2387165471d08bbd24d4c3ae4a271d2cda4c5 (patch) | |
tree | 4418a7610edf326d308f65ee0d79d4d09c341a93 | |
parent | 50381a619458017d69b044435a22fae457a5d4c1 (diff) | |
parent | 40e07d0172532ebf5750b8c2aab5ec892e42cdab (diff) | |
download | vaadin-framework-42f2387165471d08bbd24d4c3ae4a271d2cda4c5.tar.gz vaadin-framework-42f2387165471d08bbd24d4c3ae4a271d2cda4c5.zip |
Merge remote-tracking branch 'origin/master' into grid
Change-Id: I8f1f412eeb450688bba58b715eba6db9e4ae43ae
315 files changed, 18152 insertions, 10807 deletions
diff --git a/WebContent/VAADIN/themes/base/base.scss b/WebContent/VAADIN/themes/base/base.scss index 54e0916da1..0e19c8a339 100644 --- a/WebContent/VAADIN/themes/base/base.scss +++ b/WebContent/VAADIN/themes/base/base.scss @@ -55,6 +55,11 @@ margin: 0; overflow: hidden; } + +.v-modal-window-open { + overflow: hidden; +} + $font-size: 16px; $line-height: normal; @mixin base { diff --git a/WebContent/VAADIN/themes/base/common/common.scss b/WebContent/VAADIN/themes/base/common/common.scss index 07e244a76f..5cae1b26ce 100644 --- a/WebContent/VAADIN/themes/base/common/common.scss +++ b/WebContent/VAADIN/themes/base/common/common.scss @@ -227,6 +227,10 @@ input::-ms-clear { font-size: 0; line-height: normal; } +/* Set font-size in order to make Firefox scrolling better #11353 */ +.v-ff & .v-scrollable { + font-size: $font-size; +} .v-ios.v-webkit & .v-scrollable { -webkit-overflow-scrolling: touch; } diff --git a/WebContent/VAADIN/themes/base/debug/debug.scss b/WebContent/VAADIN/themes/base/debug/debug.scss index 0992f19bb9..b50245a7be 100644 --- a/WebContent/VAADIN/themes/base/debug/debug.scss +++ b/WebContent/VAADIN/themes/base/debug/debug.scss @@ -251,6 +251,14 @@ width: 100%; } + .v-debugwindow-selector > span.value { + width: 100%; + } + + .v-debugwindow-selector :hover { + background: rgba(255,32,32,0.5); + } + /* LOG */ .v-debugwindow-log { font-family: monospace; diff --git a/WebContent/VAADIN/themes/chameleon/components/textfield/textfield.scss b/WebContent/VAADIN/themes/chameleon/components/textfield/textfield.scss index 7c5c72c1df..4554672da4 100644 --- a/WebContent/VAADIN/themes/chameleon/components/textfield/textfield.scss +++ b/WebContent/VAADIN/themes/chameleon/components/textfield/textfield.scss @@ -20,7 +20,10 @@ textarea.v-textarea, input.#{$primaryStyleName}[type="text"], textarea.v-textarea, .v-filterselect { - padding: .2em; + padding-bottom: .1em; + padding-top: .1em; + padding-left: .2em; + padding-right: .2em; } input.#{$primaryStyleName}[type="text"] { @@ -29,7 +32,7 @@ input.#{$primaryStyleName}[type="text"] { input.v-widget.#{$primaryStyleName}[type="text"], .v-filterselect { - height: 1.6em; + height: 1.7em; } &.v-app input.#{$primaryStyleName}, diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index 8a917966a1..f98b7c78d1 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -77,6 +77,16 @@ </servlet> <servlet> + <!-- + This servlet is a separate instance for the sole purpose of + testing #12446 (com.vaadin.tests.components.ui.TimeoutRedirectResetsOnActivity) + because it modifies the VaadinService timeout parameters + --> + <servlet-name>VaadinApplicationRunnerWithTimeoutRedirect</servlet-name> + <servlet-class>com.vaadin.launcher.ApplicationRunnerServlet</servlet-class> + </servlet> + + <servlet> <servlet-name>VaadinApplicationRunnerWithPush</servlet-name> <servlet-class>com.vaadin.launcher.ApplicationRunnerServlet</servlet-class> <init-param> @@ -117,6 +127,11 @@ </servlet-mapping> <servlet-mapping> + <servlet-name>VaadinApplicationRunnerWithTimeoutRedirect</servlet-name> + <url-pattern>/12446/*</url-pattern> + </servlet-mapping> + + <servlet-mapping> <servlet-name>VaadinApplicationRunnerWithPush</servlet-name> <url-pattern>/run-push/*</url-pattern> </servlet-mapping> diff --git a/WebContent/statictestfiles/browserfeatures/WebkitPositionAbsoluteScrollbars.html b/WebContent/statictestfiles/browserfeatures/WebkitPositionAbsoluteScrollbars.html new file mode 100644 index 0000000000..7547816006 --- /dev/null +++ b/WebContent/statictestfiles/browserfeatures/WebkitPositionAbsoluteScrollbars.html @@ -0,0 +1,69 @@ +<!doctype> +<html><head> + <style> + #spacer { + width: 100px; + height: 100px; + background: blue; + } + #scrollable { + background: white; + border: 1px solid black; + overflow: auto; + position: relative; + width: 250px; + } + #container { + position:relative; + display:inline-block; + width:100%; + height:130px; + } + #margin { + position: absolute; + width: 200px; + top: 12px; + margin-right: 12px; + left: 12px; + height: 110px; + } + </style> + </head> + <body> + <div> + Starting point: No horizontal scrollbar<br/> + Expected: Get back to starting point after clicking through steps (do 1, do 2, cancel 1, cancel 2)<br/> + Actual: Scrollbars after doing the steps<br/><br/> + </div> +<button id="step1" onclick="step1();">Step 1 - Enlarge container</button> +<button id="step2" onclick="step2();">Step 2 - Move child</button> +<button id="step3" onclick="step3();">Step 3 - Reduce container</button> +<button id="step4" onclick="step4();">Step 4 - Return child</button> +<div id="scrollable"> +<div id="container"> +<div id="margin" style=""> +<div id="spacer" style="height: 100px; width: 100%;"> +</div> +</div> +</div> +</div> + +<script> +function step1() { + document.getElementById("container").style.width="110%"; +} +function step2() { + document.getElementById("margin").style.left="200px"; +} +function step3() { + document.getElementById("container").style.width="100%"; +} +function step4() { + document.getElementById("margin").style.left="12px"; +} + +</script> + + +</body> +</html> diff --git a/WebContent/statictestfiles/vaadinsessions.jsp b/WebContent/statictestfiles/vaadinsessions.jsp new file mode 100644 index 0000000000..b22787a203 --- /dev/null +++ b/WebContent/statictestfiles/vaadinsessions.jsp @@ -0,0 +1,54 @@ +<!DOCTYPE> +<%@page import="com.vaadin.ui.UI"%> +<%@page import="com.vaadin.server.VaadinSession"%> +<HTML> +<HEAD> +<TITLE>JSP integration</TITLE> +<style> +table { + background: #fff; +} + +td { + border: 1px solid black; + padding: .5em; +} +</style> +</HEAD> +<BODY> + <table> + <tr> + <th align="left" colspan=4>Available UIs:</th> + </tr> + <tr> + <th>Service Name</th> + <th>CSRF token</th> + <th>UI id</th> + <th>UI type</th> + <th>Main content</th> + </tr> + <% + HttpSession httpSession = request.getSession(false); + for (VaadinSession vs : VaadinSession.getAllSessions(httpSession)) { + try { + vs.lock(); + for (UI ui : vs.getUIs()) { + out.append("<tr class='uirow'>"); + out.append("<td>" + vs.getService().getServiceName() + + "</td>"); + out.append("<td>" + vs.getCsrfToken() + "</td>"); + out.append("<td>" + ui.getUIId() + "</td>"); + out.append("<td>" + ui.getClass().getName() + "</td>"); + out.append("<td>" + ui.getContent().getClass().getName() + "</td>"); + out.append("</tr>"); + + } + } finally { + vs.unlock(); + } + + } + %> + </table> +</BODY> +</HTML>
\ No newline at end of file diff --git a/all/build.xml b/all/build.xml index 1b48721ecd..36a9499dea 100644 --- a/all/build.xml +++ b/all/build.xml @@ -43,7 +43,8 @@ <property name="javadoc.dir" location="${result.dir}/javadoc" /> <property name="title" value="Vaadin ${vaadin.version} API" /> - <javadoc maxmemory="1024m" destdir="${javadoc.dir}" author="true" version="true" use="true" windowtitle="${title}" encoding="utf-8"> + <javadoc maxmemory="1024m" destdir="${javadoc.dir}" author="true" version="true" use="true" windowtitle="${title}" encoding="utf-8" + stylesheetfile="javadoc.css"> <packageset dir="${javadoc.temp.dir}"> <!-- TODO Javadoc throws ClassCastException if this is included (#9660) --> diff --git a/all/javadoc.css b/all/javadoc.css new file mode 100644 index 0000000000..ffa7288ad4 --- /dev/null +++ b/all/javadoc.css @@ -0,0 +1,236 @@ +@charset "UTF-8"; + +/* + * stylesheet for Vaadin Javadoc when compiled with Java 6 + */ +body { + background-color: rgb(244, 244, 240); + color: rgb(70, 68, 64); + font-size: 16px; + font-family: Helvetica, Arial, sans-serif; + font-weight: lighter; + line-height: 18px; + margin: 10px 14px; +} + +body[onload] { + background-color: rgb(255, 255, 255); + margin: 8px 23px; +} + +a:link,a:visited { + color: rgb(0, 180, 240); + text-decoration: none; +} + +b { + font-weight: bolder; +} + +code,pre { + font-family: Courier, monospace; +} + +dt { + font-size: 12px; + color: rgb(120, 119, 109); + text-transform: uppercase; +} + +dd>dl>dt { + font-size: 13px; + text-transform: none; +} + +h2+dl>dt { + text-transform: none; +} + +dt>pre,pre>dt { + text-transform: initial; +} + +dd { + font-size: 14px; + margin-left: 2.5em; +} + +dd:first-child { + font-size: 13px; +} + +dd>dl>dd { + font-size: 12px; +} + +h1 { + font-size: 32px +} + +h2 { + font-size: 24px; +} + +h3 { + font-size: 16px; +} + +h1,h2,h3 { + line-height: 30px; +} + +hr { + border: 1px solid rgb(233, 233, 225); +} + +pre,h2+ul { + font-size: 12px; +} + +table { + border: none; + border-collapse: collapse; +} + +td { + padding: 0; +} + +th { + padding: 0 1ch; +} + +.TableHeadingColor,.TableSubHeadingColor { + line-height: 30px; +} + +.TableHeadingColor>th,.TableHeadingColor>th>font>b,.TableSubHeadingColor>th,.TableSubHeadingColor>th>b + { + font-weight: inherit; +} + +.TableHeadingColor>th>font { + font-size: 18px; +} + +.TableSubHeadingColor { + font-size: 14px; +} + +.TableHeadingColor,.TableSubHeadingColor { + background: rgb(233, 233, 225); +} + +.TableRowColor { + background: #FFFFFF; +} + +.TableRowColor:nth-child(odd) { + background-color: rgb(244, 244, 240); +} + +.TableRowColor>td { + font-size: 12px; + border: none; + padding: 1ex 1ch +} + +.TableRowColor>td>font { + font-size: 11px; +} + +.TableHeadingColor,.TableRowColor,.TableSubHeadingColor>th { + border: none; + border-color: transparent; +} + +table[border="1"] { + border: 2px solid rgb(233, 233, 225); +} + +.FrameTitleFont { + font-size: 18px; + font-family: Helvetica, Arial, sans-serif; + font-weight: bolder; + line-height: 30px; +} + +.FrameHeadingFont { + font-size: 12px; + font-family: Helvetica, Arial, sans-serif; + font-weight: bold; + color: rgb(120, 119, 109); + text-transform: uppercase; + display: inline-block; + margin-bottom: 4px; +} + +td>.FrameHeadingFont { + margin-top: 12px; +} + +.FrameItemFont { + font-size: 90%; + font-family: Helvetica, Arial, sans-serif; +} + +.NavBarCell1 { + background-color: rgb(245, 245, 241); + border: 2px solid rgb(245, 245, 241); +} + +.NavBarCell1+td[rowspan="3"] { + display: none; +} + +.NavBarCell1,.NavBarCell1Rev { + font-size: 0; +} + +.NavBarCell1>*,.NavBarCell1Rev>* { + font-size: 14px; +} + +.NavBarCell1 .NavBarCell1,.NavBarCell1 .NavBarCell1Rev { + padding: 3px 8px; + line-height: 1; + vertical-align: baseline; +} + +.NavBarCell1Rev { + background-color: rgb(0, 180, 240); + border-radius: 3px; +} + +.NavBarFont1 { + font-family: Helvetica, Arial, sans-serif; + color: rgb(70, 68, 64); +} + +.NavBarFont1Rev { + font-family: Helvetica, Arial, sans-serif; + color: rgb(255, 255, 255); +} + +.NavBarCell2 { + font-family: Helvetica, Arial, sans-serif; + background-color: #FFFFFF; + padding-top: 6px; +} + +.NavBarCell2:first-child { + color: transparent; +} + +.NavBarCell2>font,.NavBarCell3>font { + font-size: 11px; +} + +.NavBarCell2>font>a>b { + font-weight: normal; +} + +.NavBarCell3 { + font-family: Helvetica, Arial, sans-serif; + background-color: #FFFFFF; +}
\ No newline at end of file @@ -19,6 +19,7 @@ <fileset dir="." includes="**/build.xml"> <exclude name="build.xml" /> <exclude name="build/**" /> + <exclude name="bin/**" /> <exclude name="buildhelpers/**" /> </fileset> </ivy:buildlist> diff --git a/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java b/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java index 5c3810099a..fb7b672b21 100644 --- a/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java +++ b/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java @@ -37,7 +37,6 @@ public class FetchReleaseNotesTickets { URLConnection connection = url.openConnection(); InputStream urlStream = connection.getInputStream(); - @SuppressWarnings("unchecked") List<String> tickets = IOUtils.readLines(urlStream); for (String ticket : tickets) { diff --git a/client-compiler/ivy.xml b/client-compiler/ivy.xml index f66a2e0255..f0fa5a49b0 100644 --- a/client-compiler/ivy.xml +++ b/client-compiler/ivy.xml @@ -31,33 +31,56 @@ <dependency org="commons-collections" name="commons-collections" rev="3.1" conf="build,ide -> default" /> <dependency org="commons-logging" name="commons-logging" - rev="1.1.1" conf="build,ide -> default" /> + rev="1.1.3" conf="build,ide -> default" /> <dependency org="ant" name="ant" rev="1.6.5" conf="build,ide -> default" /> <dependency org="net.sourceforge.cssparser" name="cssparser" - rev="0.9.5" conf="build,ide -> default" /> + rev="0.9.11" conf="build,ide -> default" /> <dependency org="ant" name="ant" rev="1.6.5" conf="build,ide -> default" /> <dependency org="ant" name="ant-launcher" rev="1.6.5" conf="build,ide -> default" /> - <dependency org="org.mortbay.jetty" name="jetty" rev="6.1.11" - conf="build,ide -> default" /> - <dependency org="org.mortbay.jetty" name="jetty-util" - rev="6.1.11" conf="build,ide -> default" /> + + <dependency org="org.eclipse.jetty" name="jetty-server" + rev="8.1.12.v20130726" conf="build,ide -> default"> + <exclude org="org.eclipse.jetty.orbit"></exclude> + </dependency> + <dependency org="org.eclipse.jetty" name="jetty-util" + rev="8.1.12.v20130726" conf="build,ide -> default" /> + <dependency org="org.jdesktop" name="swing-worker" rev="1.1" conf="build,ide -> default" /> <dependency org="commons-codec" name="commons-codec" - rev="1.3" conf="build,ide -> default" /> - <dependency org="commons-io" name="commons-io" rev="2.2" + rev="1.8" conf="build,ide -> default" /> + <dependency org="commons-io" name="commons-io" rev="2.4" conf="build,ide -> default" /> - <dependency org="commons-lang" name="commons-lang" - rev="2.6" conf="build,ide -> default" /> + <dependency org="org.apache.commons" name="commons-lang3" + rev="3.1" conf="build,ide -> default" /> <dependency org="org.apache.james" name="apache-mime4j" rev="0.6" conf="build,ide -> default" /> + <dependency org="org.apache.httpcomponents" name="httpclient" + rev="4.3.1" conf="build,ide -> default" /> + <dependency org="org.apache.httpcomponents" name="httpcore" + rev="4.3" conf="build,ide -> default" /> + <dependency org="org.apache.httpcomponents" name="httpmime" + rev="4.3.1" conf="build,ide -> default" /> + + <dependency org="net.sourceforge.nekohtml" name="nekohtml" + rev="1.9.19" conf="build,ide -> default" /> + <dependency org="xalan" name="serializer" rev="2.7.1" + conf="build,ide -> default" /> + <dependency org="xerces" name="xercesImpl" rev="2.11.0" + conf="build,ide -> default" /> + <dependency org="xml-apis" name="xml-apis" rev="1.4.01" + conf="build,ide -> default" /> + + <dependency org="com.ibm.icu" name="icu4j" rev="50.1.1" + conf="build,ide -> default" /> + <dependency org="com.vaadin" name="vaadin-client-compiler-deps" - rev="1.0.2" conf="build,ide -> default" /> + rev="1.1.0" conf="build,ide -> default" /> </dependencies> diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java b/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java index f8aa586064..1c06cea3fa 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java @@ -19,6 +19,8 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -74,6 +76,7 @@ public class ConnectorBundleLoaderFactory extends Generator { private final SourceWriter target; private final String baseName; private final int splitSize; + private final List<String> methodNames; // Seems to be undercounted by about 15% private int approximateChars = 0; @@ -84,6 +87,8 @@ public class ConnectorBundleLoaderFactory extends Generator { this.target = target; this.baseName = baseName; this.splitSize = splitSize; + methodNames = new ArrayList<String>(); + methodNames.add(baseName); } @Override @@ -169,17 +174,34 @@ public class ConnectorBundleLoaderFactory extends Generator { } public void splitIfNeeded() { + splitIfNeeded(false, null); + } + + public void splitIfNeeded(boolean isNative, String params) { if (approximateChars > splitSize) { String newMethod = baseName + wrapCount++; - println("%s();", newMethod); - outdent(); - println("}"); - println("private void %s() {", newMethod); + String args = params == null ? "" : params; + if (isNative) { + outdent(); + println("}-*/;"); + println("private native void %s(%s) /*-{", newMethod, args); + } else { + println("%s();", newMethod); + outdent(); + println("}"); + println("private void %s(%s) {", newMethod, args); + } + methodNames.add(newMethod); indent(); approximateChars = 0; } } + + public List<String> getMethodNames() { + return Collections.unmodifiableList(methodNames); + } + } @Override @@ -227,6 +249,8 @@ public class ConnectorBundleLoaderFactory extends Generator { w.indent(); for (ConnectorBundle bundle : bundles) { + detectBadProperties(bundle, logger); + String name = bundle.getName(); boolean isEager = name .equals(ConnectorBundleLoader.EAGER_BUNDLE_NAME); @@ -275,12 +299,34 @@ public class ConnectorBundleLoaderFactory extends Generator { w.println("private void load() {"); w.indent(); - printBundleData(logger, w, bundle); + String loadNativeJsBundle = "loadJsBundle"; + printBundleData(logger, w, bundle, loadNativeJsBundle); // Close load method w.outdent(); w.println("}"); + // Separate method for loading native JS stuff (e.g. callbacks) + String loadNativeJsMethodName = "loadNativeJs"; + w.println("private native void %s(%s store) /*-{", + loadNativeJsMethodName, TypeDataStore.class.getName()); + w.indent(); + List<String> jsMethodNames = printJsBundleData(logger, w, bundle, + loadNativeJsMethodName); + + w.outdent(); + w.println("}-*/;"); + + // Call all generated native method inside one Java method to avoid + // refercences inside native methods to each other + w.println("private void %s(%s store) {", loadNativeJsBundle, + TypeDataStore.class.getName()); + w.indent(); + printLoadJsBundleData(w, loadNativeJsBundle, jsMethodNames); + w.outdent(); + w.println("}"); + + // onFailure method declaration starts w.println("public void onFailure(Throwable reason) {"); w.indent(); @@ -315,27 +361,153 @@ public class ConnectorBundleLoaderFactory extends Generator { w.commit(logger); } + private void printLoadJsBundleData(SourceWriter w, String methodName, + List<String> methods) { + SplittingSourceWriter writer = new SplittingSourceWriter(w, methodName, + 30000); + + for (String method : methods) { + writer.println("%s(store);", method); + writer.splitIfNeeded(); + } + } + + private void detectBadProperties(ConnectorBundle bundle, TreeLogger logger) + throws UnableToCompleteException { + Map<JClassType, Set<String>> definedProperties = new HashMap<JClassType, Set<String>>(); + + for (Property property : bundle.getNeedsProperty()) { + JClassType beanType = property.getBeanType(); + Set<String> usedPropertyNames = definedProperties.get(beanType); + if (usedPropertyNames == null) { + usedPropertyNames = new HashSet<String>(); + definedProperties.put(beanType, usedPropertyNames); + } + + String name = property.getName(); + if (!usedPropertyNames.add(name)) { + logger.log(Type.ERROR, beanType.getQualifiedSourceName() + + " has multiple properties with the name " + name + + ". This can happen if there are multiple " + + "setters with identical names ignoring case."); + throw new UnableToCompleteException(); + } + if (!property.hasAccessorMethods()) { + logger.log(Type.ERROR, beanType.getQualifiedSourceName() + + " has the property '" + name + + "' without getter defined."); + throw new UnableToCompleteException(); + } + } + } + + private List<String> printJsBundleData(TreeLogger logger, SourceWriter w, + ConnectorBundle bundle, String methodName) { + SplittingSourceWriter writer = new SplittingSourceWriter(w, methodName, + 30000); + Set<Property> needsProperty = bundle.getNeedsProperty(); + for (Property property : needsProperty) { + writer.println("var data = {"); + writer.indent(); + + writer.println("setter: function(bean, value) {"); + writer.indent(); + property.writeSetterBody(logger, writer, "bean", "value"); + writer.outdent(); + writer.println("},"); + + writer.println("getter: function(bean) {"); + writer.indent(); + property.writeGetterBody(logger, writer, "bean"); + writer.outdent(); + writer.println("}"); + + writer.outdent(); + writer.println("};"); + + // Method declaration + writer.print( + "store.@%s::setPropertyData(Ljava/lang/Class;Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)", + TypeDataStore.class.getName()); + writer.println("(@%s::class, '%s', data);", property.getBeanType() + .getQualifiedSourceName(), property.getName()); + writer.println(); + writer.splitIfNeeded(true, + String.format("%s store", TypeDataStore.class.getName())); + } + return writer.getMethodNames(); + } + private void printBundleData(TreeLogger logger, SourceWriter sourceWriter, - ConnectorBundle bundle) throws UnableToCompleteException { + ConnectorBundle bundle, String loadNativeJsMethodName) + throws UnableToCompleteException { // Split into new load method when reaching approximately 30000 bytes SplittingSourceWriter w = new SplittingSourceWriter(sourceWriter, "load", 30000); + writeSuperClasses(w, bundle); writeIdentifiers(w, bundle); writeGwtConstructors(w, bundle); writeReturnTypes(w, bundle); writeInvokers(w, bundle); writeParamTypes(w, bundle); writeProxys(w, bundle); - wirteDelayedInfo(w, bundle); - writeProperites(logger, w, bundle); - writePropertyTypes(w, bundle); - writeSetters(logger, w, bundle); - writeGetters(logger, w, bundle); + writeDelayedInfo(w, bundle); + + w.println("%s(store);", loadNativeJsMethodName); + + // Must use Java code to generate Type data (because of Type[]), doing + // this after the JS property data has been initialized + writePropertyTypes(logger, w, bundle); writeSerializers(logger, w, bundle); writeDelegateToWidget(logger, w, bundle); } + private void writeSuperClasses(SplittingSourceWriter w, + ConnectorBundle bundle) { + List<JClassType> needsSuperclass = new ArrayList<JClassType>( + bundle.getNeedsSuperclass()); + // Emit in hierarchy order to ensure superclass is defined when + // referenced + Collections.sort(needsSuperclass, new Comparator<JClassType>() { + + @Override + public int compare(JClassType type1, JClassType type2) { + int depthDiff = getDepth(type1) - getDepth(type2); + if (depthDiff != 0) { + return depthDiff; + } else { + // Just something to get a stable compare + return type1.getName().compareTo(type2.getName()); + } + } + + private int getDepth(JClassType type) { + int depth = 0; + while (type != null) { + depth++; + type = type.getSuperclass(); + } + return depth; + } + }); + + for (JClassType jClassType : needsSuperclass) { + JClassType superclass = jClassType.getSuperclass(); + while (superclass != null && !superclass.isPublic()) { + superclass = superclass.getSuperclass(); + } + String classLiteralString; + if (superclass == null) { + classLiteralString = "null"; + } else { + classLiteralString = getClassLiteralString(superclass); + } + w.println("store.setSuperClass(%s, %s);", + getClassLiteralString(jClassType), classLiteralString); + } + } + private void writeDelegateToWidget(TreeLogger logger, SplittingSourceWriter w, ConnectorBundle bundle) { Set<Property> needsDelegateToWidget = bundle.getNeedsDelegateToWidget(); @@ -378,64 +550,9 @@ public class ConnectorBundleLoaderFactory extends Generator { } } - private void writeGetters(TreeLogger logger, SplittingSourceWriter w, + private void writePropertyTypes(TreeLogger logger, SplittingSourceWriter w, ConnectorBundle bundle) { - Set<Property> properties = bundle.getNeedsSetter(); - for (Property property : properties) { - w.print("store.setGetter("); - writeClassLiteral(w, property.getBeanType()); - w.print(", \""); - w.print(escape(property.getName())); - w.println("\", new Invoker() {"); - w.indent(); - - w.println("public Object invoke(Object bean, Object[] params) {"); - w.indent(); - - property.writeGetterBody(logger, w, "bean"); - w.println(); - - w.outdent(); - w.println("}"); - - w.outdent(); - w.println("});"); - - w.splitIfNeeded(); - } - } - - private void writeSetters(TreeLogger logger, SplittingSourceWriter w, - ConnectorBundle bundle) { - Set<Property> properties = bundle.getNeedsSetter(); - for (Property property : properties) { - w.print("store.setSetter("); - writeClassLiteral(w, property.getBeanType()); - w.print(", \""); - w.print(escape(property.getName())); - w.println("\", new Invoker() {"); - w.indent(); - - w.println("public Object invoke(Object bean, Object[] params) {"); - w.indent(); - - property.writeSetterBody(logger, w, "bean", "params[0]"); - - w.println("return null;"); - - w.outdent(); - w.println("}"); - - w.outdent(); - w.println("});"); - - w.splitIfNeeded(); - } - } - - private void writePropertyTypes(SplittingSourceWriter w, - ConnectorBundle bundle) { - Set<Property> properties = bundle.getNeedsType(); + Set<Property> properties = bundle.getNeedsProperty(); for (Property property : properties) { w.print("store.setPropertyType("); writeClassLiteral(w, property.getBeanType()); @@ -449,40 +566,7 @@ public class ConnectorBundleLoaderFactory extends Generator { } } - private void writeProperites(TreeLogger logger, SplittingSourceWriter w, - ConnectorBundle bundle) throws UnableToCompleteException { - Set<JClassType> needsPropertyListing = bundle.getNeedsPropertyListing(); - for (JClassType type : needsPropertyListing) { - w.print("store.setProperties("); - writeClassLiteral(w, type); - w.print(", new String[] {"); - - Set<String> usedPropertyNames = new HashSet<String>(); - Collection<Property> properties = bundle.getProperties(type); - for (Property property : properties) { - String name = property.getName(); - if (!usedPropertyNames.add(name)) { - logger.log( - Type.ERROR, - type.getQualifiedSourceName() - + " has multiple properties with the name " - + name - + ". This can happen if there are multiple setters with identical names exect casing."); - throw new UnableToCompleteException(); - } - - w.print("\""); - w.print(name); - w.print("\", "); - } - - w.println("});"); - - w.splitIfNeeded(); - } - } - - private void wirteDelayedInfo(SplittingSourceWriter w, + private void writeDelayedInfo(SplittingSourceWriter w, ConnectorBundle bundle) { Map<JClassType, Set<JMethod>> needsDelayedInfo = bundle .getNeedsDelayedInfo(); diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java index cbdd3e89aa..0064a24aef 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java @@ -59,7 +59,7 @@ public class ConnectorBundle { private final Set<JType> needsSerializeSupport = new HashSet<JType>(); private final Map<JType, GeneratedSerializer> serializers = new HashMap<JType, GeneratedSerializer>(); - private final Set<JClassType> needsPropertyList = new HashSet<JClassType>(); + private final Set<JClassType> needsSuperClass = new HashSet<JClassType>(); private final Set<JClassType> needsGwtConstructor = new HashSet<JClassType>(); private final Set<JClassType> visitedTypes = new HashSet<JClassType>(); private final Set<JClassType> needsProxySupport = new HashSet<JClassType>(); @@ -70,9 +70,7 @@ public class ConnectorBundle { private final Map<JClassType, Set<JMethod>> needsParamTypes = new HashMap<JClassType, Set<JMethod>>(); private final Map<JClassType, Set<JMethod>> needsDelayedInfo = new HashMap<JClassType, Set<JMethod>>(); - private final Set<Property> needsSetter = new HashSet<Property>(); - private final Set<Property> needsType = new HashSet<Property>(); - private final Set<Property> needsGetter = new HashSet<Property>(); + private final Set<Property> needsProperty = new HashSet<Property>(); private final Set<Property> needsDelegateToWidget = new HashSet<Property>(); private ConnectorBundle(String name, ConnectorBundle previousBundle, @@ -246,16 +244,18 @@ public class ConnectorBundle { logger.log(Type.INFO, "Will serialize " + type + " as a bean"); - setNeedsPropertyList(typeAsClass); + JClassType needsSuperClass = typeAsClass; + while (needsSuperClass != null) { + if (needsSuperClass.isPublic()) { + setNeedsSuperclass(needsSuperClass); + } + needsSuperClass = needsSuperClass.getSuperclass(); + } for (Property property : getProperties(typeAsClass)) { setNeedsGwtConstructor(property.getBeanType()); - setNeedsSetter(property); - // Getters needed for reading previous value that should be - // passed to sub encoder - setNeedsGetter(property); - setNeedsType(property); + setNeedsProperty(property); JType propertyType = property.getPropertyType(); setNeedsSerialize(propertyType); @@ -304,80 +304,42 @@ public class ConnectorBundle { return Collections.unmodifiableMap(serializers); } - private void setNeedsGetter(Property property) { - if (!isNeedsGetter(property)) { - needsGetter.add(property); + private void setNeedsSuperclass(JClassType typeAsClass) { + if (!isNeedsSuperClass(typeAsClass)) { + needsSuperClass.add(typeAsClass); } } - private boolean isNeedsGetter(Property property) { - if (needsGetter.contains(property)) { + private boolean isNeedsSuperClass(JClassType typeAsClass) { + if (needsSuperClass.contains(typeAsClass)) { return true; } else { return previousBundle != null - && previousBundle.isNeedsGetter(property); + && previousBundle.isNeedsSuperClass(typeAsClass); } } - public Set<Property> getNeedsGetter() { - return Collections.unmodifiableSet(needsGetter); + public Set<JClassType> getNeedsSuperclass() { + return Collections.unmodifiableSet(needsSuperClass); } - private void setNeedsType(Property property) { - if (!isNeedsType(property)) { - needsType.add(property); + private void setNeedsProperty(Property property) { + if (!isNeedsProperty(property)) { + needsProperty.add(property); } } - public Set<Property> getNeedsType() { - return Collections.unmodifiableSet(needsType); - } - - private boolean isNeedsType(Property property) { - if (needsType.contains(property)) { + private boolean isNeedsProperty(Property property) { + if (needsProperty.contains(property)) { return true; } else { return previousBundle != null - && previousBundle.isNeedsType(property); + && previousBundle.isNeedsProperty(property); } } - public void setNeedsSetter(Property property) { - if (!isNeedsSetter(property)) { - needsSetter.add(property); - } - } - - private boolean isNeedsSetter(Property property) { - if (needsSetter.contains(property)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsSetter(property); - } - } - - public Set<Property> getNeedsSetter() { - return Collections.unmodifiableSet(needsSetter); - } - - private void setNeedsPropertyList(JClassType type) { - if (!isNeedsPropertyList(type)) { - needsPropertyList.add(type); - } - } - - private boolean isNeedsPropertyList(JClassType type) { - if (needsPropertyList.contains(type)) { - return true; - } else { - return previousBundle != null - && previousBundle.isNeedsPropertyList(type); - } - } - - public Set<JClassType> getNeedsPropertyListing() { - return Collections.unmodifiableSet(needsPropertyList); + public Set<Property> getNeedsProperty() { + return Collections.unmodifiableSet(needsProperty); } public Collection<Property> getProperties(JClassType type) { @@ -430,11 +392,11 @@ public class ConnectorBundle { } private static boolean isClientRpc(JClassType type) { - return isType(type, ClientRpc.class); + return isInterfaceType(type, ClientRpc.class); } private static boolean isServerRpc(JClassType type) { - return isType(type, ServerRpc.class); + return isInterfaceType(type, ServerRpc.class); } public static boolean isConnectedConnector(JClassType type) { @@ -451,6 +413,10 @@ public class ConnectorBundle { return isConnected(type) && isType(type, ComponentConnector.class); } + private static boolean isInterfaceType(JClassType type, Class<?> class1) { + return type.isInterface() != null && isType(type, class1); + } + private static boolean isType(JClassType type, Class<?> class1) { try { return type.getOracle().getType(class1.getName()) @@ -619,4 +585,4 @@ public class ConnectorBundle { return Collections.unmodifiableSet(needsDelegateToWidget); } -}
\ No newline at end of file +} diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java index 86b8260885..e9ff4587fb 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/FieldProperty.java @@ -38,18 +38,25 @@ public class FieldProperty extends Property { } @Override + public boolean hasAccessorMethods() { + return true; + } + + @Override public void writeSetterBody(TreeLogger logger, SourceWriter w, String beanVariable, String valueVariable) { - w.print("((%s) %s).%s = (%s)%s;", getBeanType() - .getQualifiedSourceName(), beanVariable, getName(), - getUnboxedPropertyTypeName(), valueVariable); + w.println("%s.@%s::%s = %s;", beanVariable, getBeanType() + .getQualifiedSourceName(), getName(), unboxValue(valueVariable)); } @Override public void writeGetterBody(TreeLogger logger, SourceWriter w, String beanVariable) { - w.print("return ((%s) %s).%s;", getBeanType().getQualifiedSourceName(), - beanVariable, getName()); + String value = String.format("%s.@%s::%s", beanVariable, getBeanType() + .getQualifiedSourceName(), getName()); + w.print("return "); + w.print(boxValue(value)); + w.println(";"); } public static Collection<FieldProperty> findProperties(JClassType type) { @@ -57,7 +64,7 @@ public class FieldProperty extends Property { List<JField> fields = getPublicFields(type); for (JField field : fields) { - properties.add(new FieldProperty(type, field)); + properties.add(new FieldProperty(field.getEnclosingType(), field)); } return properties; diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/MethodProperty.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/MethodProperty.java index 3c317e033e..1d9deef265 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/MethodProperty.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/MethodProperty.java @@ -19,7 +19,9 @@ package com.vaadin.server.widgetsetutils.metadata; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.typeinfo.JClassType; @@ -31,18 +33,29 @@ public class MethodProperty extends Property { private final JMethod setter; - private MethodProperty(JClassType beanType, JMethod setter) { + private final String getter; + + private MethodProperty(JClassType beanType, JMethod setter, String getter) { super(getTransportFieldName(setter), beanType, setter .getParameterTypes()[0]); this.setter = setter; + this.getter = getter; + } + + @Override + public boolean hasAccessorMethods() { + return getter != null; } public static Collection<MethodProperty> findProperties(JClassType type) { Collection<MethodProperty> properties = new ArrayList<MethodProperty>(); - List<JMethod> setters = getSetters(type); + Set<String> getters = new HashSet<String>(); + List<JMethod> setters = getSetters(type, getters); for (JMethod setter : setters) { - properties.add(new MethodProperty(type, setter)); + String getter = findGetter(type, setter); + properties.add(new MethodProperty(setter.getEnclosingType(), + setter, getters.contains(getter) ? getter : null)); } return properties; @@ -53,9 +66,12 @@ public class MethodProperty extends Property { * * @param beanType * The type to check + * @param getters + * Set that will be filled with names of getters. * @return A list of setter methods from the class and its parents */ - private static List<JMethod> getSetters(JClassType beanType) { + private static List<JMethod> getSetters(JClassType beanType, + Set<String> getters) { List<JMethod> setterMethods = new ArrayList<JMethod>(); while (beanType != null @@ -63,13 +79,19 @@ public class MethodProperty extends Property { Object.class.getName())) { for (JMethod method : beanType.getMethods()) { // Process all setters that have corresponding fields - if (!method.isPublic() || method.isStatic() - || !method.getName().startsWith("set") - || method.getParameterTypes().length != 1) { - // Not setter, skip to next method + if (!method.isPublic() || method.isStatic()) { + // Not getter/setter, skip to next method continue; } - setterMethods.add(method); + String methodName = method.getName(); + if (methodName.startsWith("set") + && method.getParameterTypes().length == 1) { + setterMethods.add(method); + } else if (method.getParameterTypes().length == 0 + && methodName.startsWith("is") + || methodName.startsWith("get")) { + getters.add(methodName); + } } beanType = beanType.getSuperclass(); } @@ -78,34 +100,26 @@ public class MethodProperty extends Property { } @Override - public void writeSetterBody(TreeLogger logger, SourceWriter w, - String beanVariable, String valueVariable) { - w.print("(("); - w.print(getBeanType().getQualifiedSourceName()); - w.print(") "); - w.print(beanVariable); - w.print(")."); - w.print(setter.getName()); - w.print("(("); - w.print(getUnboxedPropertyTypeName()); - w.print(") "); - w.print(valueVariable); - w.println(");"); + public void writeGetterBody(TreeLogger logger, SourceWriter w, + String beanVariable) { + String value = String.format("%s.@%s::%s()()", beanVariable, + getBeanType().getQualifiedSourceName(), getter); + w.print("return "); + w.print(boxValue(value)); + w.println(";"); } @Override - public void writeGetterBody(TreeLogger logger, SourceWriter w, - String beanVariable) { - w.print("return (("); - w.print(getBeanType().getQualifiedSourceName()); - w.print(") "); - w.print(beanVariable); - w.print(")."); - w.print(findGetter(getBeanType(), setter)); - w.print("();"); + public void writeSetterBody(TreeLogger logger, SourceWriter w, + String beanVariable, String valueVariable) { + w.println("%s.@%s::%s(%s)(%s);", beanVariable, getBeanType() + .getQualifiedSourceName(), setter.getName(), setter + .getParameterTypes()[0].getJNISignature(), + unboxValue(valueVariable)); + } - private String findGetter(JClassType beanType, JMethod setterMethod) { + private static String findGetter(JClassType beanType, JMethod setterMethod) { JType setterParameterType = setterMethod.getParameterTypes()[0]; String fieldName = setterMethod.getName().substring(3); if (setterParameterType.getQualifiedSourceName().equals( diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/Property.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/Property.java index 02aad7bdf2..381af23b42 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/Property.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/Property.java @@ -53,6 +53,28 @@ public abstract class Property { } } + public String boxValue(String codeSnippet) { + JPrimitiveType primitive = propertyType.isPrimitive(); + if (primitive == null) { + return codeSnippet; + } else { + return String.format("@%s::valueOf(%s)(%s)", + primitive.getQualifiedBoxedSourceName(), + propertyType.getJNISignature(), codeSnippet); + } + } + + public String unboxValue(String codeSnippet) { + JPrimitiveType primitive = propertyType.isPrimitive(); + if (primitive == null) { + return codeSnippet; + } else { + return String.format("%s.@%s::%sValue()()", codeSnippet, + primitive.getQualifiedBoxedSourceName(), + primitive.getSimpleSourceName()); + } + } + public JClassType getBeanType() { return beanType; } @@ -63,6 +85,8 @@ public abstract class Property { public abstract void writeGetterBody(TreeLogger logger, SourceWriter w, String beanVariable); + public abstract boolean hasAccessorMethods(); + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/client/src/com/vaadin/DefaultWidgetSet.gwt.xml b/client/src/com/vaadin/DefaultWidgetSet.gwt.xml index 3aba1f6fee..2719493853 100755 --- a/client/src/com/vaadin/DefaultWidgetSet.gwt.xml +++ b/client/src/com/vaadin/DefaultWidgetSet.gwt.xml @@ -10,4 +10,8 @@ <entry-point class="com.vaadin.client.ApplicationConfiguration" /> + <!-- Since 7.2. Compile all permutations (browser support) into one Javascript + file. Speeds up compilation and does not make the Javascript significantly + larger. --> + <collapse-all-properties /> </module> diff --git a/client/src/com/vaadin/Vaadin.gwt.xml b/client/src/com/vaadin/Vaadin.gwt.xml index a1dca07a1c..d4eb454e86 100644 --- a/client/src/com/vaadin/Vaadin.gwt.xml +++ b/client/src/com/vaadin/Vaadin.gwt.xml @@ -59,6 +59,7 @@ <!-- Use the new cross site linker to get a nocache.js without document.write --> <add-linker name="xsiframe" /> + <extend-property name="user.agent" values="opera" /> <!-- Remove IE6/IE7 permutation as they are not supported --> <set-property name="user.agent" value="ie8,ie9,ie10,gecko1_8,safari,opera" /> diff --git a/client/src/com/vaadin/client/ApplicationConfiguration.java b/client/src/com/vaadin/client/ApplicationConfiguration.java index 7a70080c7e..1a5b0d836f 100644 --- a/client/src/com/vaadin/client/ApplicationConfiguration.java +++ b/client/src/com/vaadin/client/ApplicationConfiguration.java @@ -41,6 +41,7 @@ import com.vaadin.client.debug.internal.LogSection; import com.vaadin.client.debug.internal.NetworkSection; import com.vaadin.client.debug.internal.ProfilerSection; import com.vaadin.client.debug.internal.Section; +import com.vaadin.client.debug.internal.TestBenchSection; import com.vaadin.client.debug.internal.VDebugWindow; import com.vaadin.client.metadata.BundleLoadCallback; import com.vaadin.client.metadata.ConnectorBundleLoader; @@ -511,6 +512,30 @@ public class ApplicationConfiguration implements EntryPoint { } } + /** + * Returns all tags for given class. Tags are used in + * {@link ApplicationConfiguration} to keep track of different classes and + * their hierarchy + * + * @since 7.2 + * @param classname + * name of class which tags we want + * @return Integer array of tags pointing to this classname + */ + public Integer[] getTagsForServerSideClassName(String classname) { + List<Integer> tags = new ArrayList<Integer>(); + + for (Map.Entry<Integer, String> entry : tagToServerSideClassName + .entrySet()) { + if (classname.equals(entry.getValue())) { + tags.add(entry.getKey()); + } + } + + Integer[] out = new Integer[tags.size()]; + return tags.toArray(out); + } + public Integer getParentTag(int tag) { return componentInheritanceMap.get(tag); } @@ -595,6 +620,7 @@ public class ApplicationConfiguration implements EntryPoint { window.addSection((Section) GWT.create(InfoSection.class)); window.addSection((Section) GWT.create(HierarchySection.class)); window.addSection((Section) GWT.create(NetworkSection.class)); + window.addSection((Section) GWT.create(TestBenchSection.class)); if (Profiler.isEnabled()) { window.addSection((Section) GWT.create(ProfilerSection.class)); } @@ -760,5 +786,4 @@ public class ApplicationConfiguration implements EntryPoint { private static final Logger getLogger() { return Logger.getLogger(ApplicationConfiguration.class.getName()); } - } diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index da41543894..b84d8a376f 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -1,4 +1,4 @@ -/* +/* * Copyright 2000-2013 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not @@ -65,16 +65,17 @@ import com.google.gwt.user.client.Window.ClosingHandler; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConfiguration.ErrorMessage; -import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent; import com.vaadin.client.ResourceLoader.ResourceLoadEvent; import com.vaadin.client.ResourceLoader.ResourceLoadListener; import com.vaadin.client.communication.HasJavaScriptConnectorHelper; +import com.vaadin.client.communication.Heartbeat; import com.vaadin.client.communication.JavaScriptMethodInvocation; import com.vaadin.client.communication.JsonDecoder; import com.vaadin.client.communication.JsonEncoder; import com.vaadin.client.communication.PushConnection; import com.vaadin.client.communication.RpcManager; import com.vaadin.client.communication.StateChangeEvent; +import com.vaadin.client.componentlocator.ComponentLocator; import com.vaadin.client.extensions.AbstractExtensionConnector; import com.vaadin.client.metadata.ConnectorBundleLoader; import com.vaadin.client.metadata.Method; @@ -363,7 +364,7 @@ public class ApplicationConnection { * * To listen for the event add a {@link ApplicationStoppedHandler} by * invoking - * {@link ApplicationConnection#addHandler(ApplicationStoppedEvent.Type, ApplicationStoppedHandler)} + * {@link ApplicationConnection#addHandler(ApplicationConnection.ApplicationStoppedEvent.Type, ApplicationStoppedHandler)} * to the {@link ApplicationConnection} * * @since 7.1.8 @@ -428,6 +429,8 @@ public class ApplicationConnection { private VLoadingIndicator loadingIndicator; + private Heartbeat heartbeat = GWT.create(Heartbeat.class); + public static class MultiStepDuration extends Duration { private int previousStep = elapsedMillis(); @@ -490,7 +493,7 @@ public class ApplicationConnection { getLoadingIndicator().show(); - scheduleHeartbeat(); + heartbeat.init(this); Window.addWindowClosingHandler(new ClosingHandler() { @Override @@ -547,38 +550,47 @@ public class ApplicationConnection { private native void initializeTestbenchHooks( ComponentLocator componentLocator, String TTAppId) /*-{ - var ap = this; - var client = {}; - client.isActive = $entry(function() { - return ap.@com.vaadin.client.ApplicationConnection::hasActiveRequest()() - || ap.@com.vaadin.client.ApplicationConnection::isExecutingDeferredCommands()(); - }); - var vi = ap.@com.vaadin.client.ApplicationConnection::getVersionInfo()(); - if (vi) { - client.getVersionInfo = function() { - return vi; - } - } + var ap = this; + var client = {}; + client.isActive = $entry(function() { + return ap.@com.vaadin.client.ApplicationConnection::hasActiveRequest()() + || ap.@com.vaadin.client.ApplicationConnection::isExecutingDeferredCommands()(); + }); + var vi = ap.@com.vaadin.client.ApplicationConnection::getVersionInfo()(); + if (vi) { + client.getVersionInfo = function() { + return vi; + } + } - client.getProfilingData = $entry(function() { - var pd = [ - ap.@com.vaadin.client.ApplicationConnection::lastProcessingTime, + client.getProfilingData = $entry(function() { + var pd = [ + ap.@com.vaadin.client.ApplicationConnection::lastProcessingTime, ap.@com.vaadin.client.ApplicationConnection::totalProcessingTime - ]; - pd = pd.concat(ap.@com.vaadin.client.ApplicationConnection::serverTimingInfo); - pd[pd.length] = ap.@com.vaadin.client.ApplicationConnection::bootstrapTime; - return pd; - }); + ]; + pd = pd.concat(ap.@com.vaadin.client.ApplicationConnection::serverTimingInfo); + pd[pd.length] = ap.@com.vaadin.client.ApplicationConnection::bootstrapTime; + return pd; + }); - client.getElementByPath = $entry(function(id) { - return componentLocator.@com.vaadin.client.ComponentLocator::getElementByPath(Ljava/lang/String;)(id); - }); - client.getPathForElement = $entry(function(element) { - return componentLocator.@com.vaadin.client.ComponentLocator::getPathForElement(Lcom/google/gwt/user/client/Element;)(element); - }); - client.initializing = false; + client.getElementByPath = $entry(function(id) { + return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementByPath(Ljava/lang/String;)(id); + }); + client.getElementByPathStartingAt = $entry(function(id, element) { + return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementByPathStartingAt(Ljava/lang/String;Lcom/google/gwt/user/client/Element;)(id, element); + }); + client.getElementsByPath = $entry(function(id) { + return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementsByPath(Ljava/lang/String;)(id); + }); + client.getElementsByPathStartingAt = $entry(function(id, element) { + return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getElementsByPathStartingAt(Ljava/lang/String;Lcom/google/gwt/user/client/Element;)(id, element); + }); + client.getPathForElement = $entry(function(element) { + return componentLocator.@com.vaadin.client.componentlocator.ComponentLocator::getPathForElement(Lcom/google/gwt/user/client/Element;)(element); + }); + client.initializing = false; - $wnd.vaadin.clients[TTAppId] = client; + $wnd.vaadin.clients[TTAppId] = client; }-*/; private static native final int calculateBootstrapTime() @@ -1460,6 +1472,9 @@ public class ApplicationConnection { if (meta.containsKey("timedRedirect")) { final ValueMap timedRedirect = meta .getValueMap("timedRedirect"); + if (redirectTimer != null) { + redirectTimer.cancel(); + } redirectTimer = new Timer() { @Override public void run() { @@ -3311,20 +3326,11 @@ public class ApplicationConnection { * interval elapses if the interval is a positive number. Otherwise, does * nothing. * - * @see #sendHeartbeat() - * @see ApplicationConfiguration#getHeartbeatInterval() + * @deprecated as of 7.2, use {@link Heartbeat#schedule()} instead */ + @Deprecated protected void scheduleHeartbeat() { - final int interval = getConfiguration().getHeartbeatInterval(); - if (interval > 0) { - VConsole.log("Scheduling heartbeat in " + interval + " seconds"); - new Timer() { - @Override - public void run() { - sendHeartbeat(); - } - }.schedule(interval * 1000); - } + heartbeat.schedule(); } /** @@ -3333,51 +3339,12 @@ public class ApplicationConnection { * Heartbeat requests are used to inform the server that the client-side is * still alive. If the client page is closed or the connection lost, the * server will eventually close the inactive UI. - * <p> - * <b>TODO</b>: Improved error handling, like in doUidlRequest(). * - * @see #scheduleHeartbeat() + * @deprecated as of 7.2, use {@link Heartbeat#send()} instead */ + @Deprecated protected void sendHeartbeat() { - final String uri = addGetParameters( - translateVaadinUri(ApplicationConstants.APP_PROTOCOL_PREFIX - + ApplicationConstants.HEARTBEAT_PATH + '/'), - UIConstants.UI_ID_PARAMETER + "=" - + getConfiguration().getUIId()); - - final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri); - - final RequestCallback callback = new RequestCallback() { - - @Override - public void onResponseReceived(Request request, Response response) { - int status = response.getStatusCode(); - if (status == Response.SC_OK) { - // TODO Permit retry in some error situations - VConsole.log("Heartbeat response OK"); - scheduleHeartbeat(); - } else if (status == Response.SC_GONE) { - showSessionExpiredError(null); - } else { - VConsole.error("Failed sending heartbeat to server. Error code: " - + status); - } - } - - @Override - public void onError(Request request, Throwable exception) { - VConsole.error("Exception sending heartbeat: " + exception); - } - }; - - rb.setCallback(callback); - - try { - VConsole.log("Sending heartbeat request..."); - rb.send(); - } catch (RequestException re) { - callback.onError(null, re); - } + heartbeat.send(); } /** diff --git a/client/src/com/vaadin/client/ComponentLocator.java b/client/src/com/vaadin/client/ComponentLocator.java index af934470c2..ef7ccc3b65 100644 --- a/client/src/com/vaadin/client/ComponentLocator.java +++ b/client/src/com/vaadin/client/ComponentLocator.java @@ -15,706 +15,20 @@ */ package com.vaadin.client; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.HasWidgets; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.ui.SubPartAware; -import com.vaadin.client.ui.VCssLayout; -import com.vaadin.client.ui.VGridLayout; -import com.vaadin.client.ui.VOverlay; -import com.vaadin.client.ui.VTabsheetPanel; -import com.vaadin.client.ui.VUI; -import com.vaadin.client.ui.VWindow; -import com.vaadin.client.ui.orderedlayout.Slot; -import com.vaadin.client.ui.orderedlayout.VAbstractOrderedLayout; -import com.vaadin.client.ui.window.WindowConnector; -import com.vaadin.shared.AbstractComponentState; -import com.vaadin.shared.Connector; -import com.vaadin.shared.communication.SharedState; - /** * ComponentLocator provides methods for generating a String locator for a given * DOM element and for locating a DOM element using a String locator. + * + * @since 5.4 + * @deprecated Moved to com.vaadin.client.componentlocator.ComponentLocator */ -public class ComponentLocator { - - /** - * Separator used in the String locator between a parent and a child widget. - */ - private static final String PARENTCHILD_SEPARATOR = "/"; - - /** - * Separator used in the String locator between the part identifying the - * containing widget and the part identifying the target element within the - * widget. - */ - private static final String SUBPART_SEPARATOR = "#"; - - /** - * String that identifies the root panel when appearing first in the String - * locator. - */ - private static final String ROOT_ID = "Root"; - - /** - * Reference to ApplicationConnection instance. - */ - private ApplicationConnection client; - +public class ComponentLocator extends com.vaadin.client.componentlocator.ComponentLocator { /** * Construct a ComponentLocator for the given ApplicationConnection. - * - * @param client - * ApplicationConnection instance for the application. + * + * @param client ApplicationConnection instance for the application. */ public ComponentLocator(ApplicationConnection client) { - this.client = client; - } - - /** - * Generates a String locator which uniquely identifies the target element. - * The {@link #getElementByPath(String)} method can be used for the inverse - * operation, i.e. locating an element based on the return value from this - * method. - * <p> - * Note that getElementByPath(getPathForElement(element)) == element is not - * always true as {@link #getPathForElement(Element)} can return a path to - * another element if the widget determines an action on the other element - * will give the same result as the action on the target element. - * </p> - * - * @since 5.4 - * @param targetElement - * The element to generate a path for. - * @return A String locator that identifies the target element or null if a - * String locator could not be created. - */ - public String getPathForElement(Element targetElement) { - String pid = null; - - targetElement = getElement(targetElement); - - Element e = targetElement; - - while (true) { - pid = ConnectorMap.get(client).getConnectorId(e); - if (pid != null) { - break; - } - - e = DOM.getParent(e); - if (e == null) { - break; - } - } - - Widget w = null; - if (pid != null) { - // If we found a Paintable then we use that as reference. We should - // find the Paintable for all but very special cases (like - // overlays). - w = ((ComponentConnector) ConnectorMap.get(client) - .getConnector(pid)).getWidget(); - - /* - * Still if the Paintable contains a widget that implements - * SubPartAware, we want to use that as a reference - */ - Widget targetParent = findParentWidget(targetElement, w); - while (targetParent != w && targetParent != null) { - if (targetParent instanceof SubPartAware) { - /* - * The targetParent widget is a child of the Paintable and - * the first parent (of the targetElement) that implements - * SubPartAware - */ - w = targetParent; - break; - } - targetParent = targetParent.getParent(); - } - } - if (w == null) { - // Check if the element is part of a widget that is attached - // directly to the root panel - RootPanel rootPanel = RootPanel.get(); - int rootWidgetCount = rootPanel.getWidgetCount(); - for (int i = 0; i < rootWidgetCount; i++) { - Widget rootWidget = rootPanel.getWidget(i); - if (rootWidget.getElement().isOrHasChild(targetElement)) { - // The target element is contained by this root widget - w = findParentWidget(targetElement, rootWidget); - break; - } - } - if (w != null) { - // We found a widget but we should still see if we find a - // SubPartAware implementor (we cannot find the Paintable as - // there is no link from VOverlay to its paintable/owner). - Widget subPartAwareWidget = findSubPartAwareParentWidget(w); - if (subPartAwareWidget != null) { - w = subPartAwareWidget; - } - } - } - - if (w == null) { - // Containing widget not found - return null; - } - - // Determine the path for the target widget - String path = getPathForWidget(w); - if (path == null) { - /* - * No path could be determined for the target widget. Cannot create - * a locator string. - */ - return null; - } - - // The parent check is a work around for Firefox 15 which fails to - // compare elements properly (#9534) - if (w.getElement() == targetElement) { - /* - * We are done if the target element is the root of the target - * widget. - */ - return path; - } else if (w instanceof SubPartAware) { - /* - * If the widget can provide an identifier for the targetElement we - * let it do that - */ - String elementLocator = ((SubPartAware) w) - .getSubPartName(targetElement); - if (elementLocator != null) { - return path + SUBPART_SEPARATOR + elementLocator; - } - } - /* - * If everything else fails we use the DOM path to identify the target - * element - */ - String domPath = getDOMPathForElement(targetElement, w.getElement()); - if (domPath == null) { - return path; - } else { - return path + domPath; - } - } - - /** - * Returns the element passed to the method. Or in case of Firefox 15, - * returns the real element that is in the DOM instead of the element passed - * to the method (which is the same element but not ==). - * - * @param targetElement - * the element to return - * @return the element passed to the method - */ - private Element getElement(Element targetElement) { - if (targetElement == null) { - return null; - } - - if (!BrowserInfo.get().isFirefox()) { - return targetElement; - } - - if (BrowserInfo.get().getBrowserMajorVersion() != 15) { - return targetElement; - } - - // Firefox 15, you make me sad - if (targetElement.getNextSibling() != null) { - return (Element) targetElement.getNextSibling() - .getPreviousSibling(); - } - if (targetElement.getPreviousSibling() != null) { - return (Element) targetElement.getPreviousSibling() - .getNextSibling(); - } - // No siblings so this is the only child - return (Element) targetElement.getParentNode().getChild(0); - } - - /** - * Finds the first widget in the hierarchy (moving upwards) that implements - * SubPartAware. Returns the SubPartAware implementor or null if none is - * found. - * - * @param w - * The widget to start from. This is returned if it implements - * SubPartAware. - * @return The first widget (upwards in hierarchy) that implements - * SubPartAware or null - */ - private Widget findSubPartAwareParentWidget(Widget w) { - - while (w != null) { - if (w instanceof SubPartAware) { - return w; - } - w = w.getParent(); - } - return null; - } - - /** - * Returns the first widget found when going from {@code targetElement} - * upwards in the DOM hierarchy, assuming that {@code ancestorWidget} is a - * parent of {@code targetElement}. - * - * @param targetElement - * @param ancestorWidget - * @return The widget whose root element is a parent of - * {@code targetElement}. - */ - private Widget findParentWidget(Element targetElement, Widget ancestorWidget) { - /* - * As we cannot resolve Widgets from the element we start from the - * widget and move downwards to the correct child widget, as long as we - * find one. - */ - if (ancestorWidget instanceof HasWidgets) { - for (Widget w : ((HasWidgets) ancestorWidget)) { - if (w.getElement().isOrHasChild(targetElement)) { - return findParentWidget(targetElement, w); - } - } - } - - // No children found, this is it - return ancestorWidget; - } - - /** - * Locates an element based on a DOM path and a base element. - * - * @param baseElement - * The base element which the path is relative to - * @param path - * String locator (consisting of domChild[x] parts) that - * identifies the element - * @return The element identified by path, relative to baseElement or null - * if the element could not be found. - */ - private Element getElementByDOMPath(Element baseElement, String path) { - String parts[] = path.split(PARENTCHILD_SEPARATOR); - Element element = baseElement; - - for (String part : parts) { - if (part.startsWith("domChild[")) { - String childIndexString = part.substring("domChild[".length(), - part.length() - 1); - - if (Util.findWidget(baseElement, null) instanceof VAbstractOrderedLayout) { - if (element.hasChildNodes()) { - Element e = element.getFirstChildElement().cast(); - String cn = e.getClassName(); - if (cn != null - && (cn.equals("v-expand") || cn - .contains("v-has-caption"))) { - element = e; - } - } - } - - try { - int childIndex = Integer.parseInt(childIndexString); - element = DOM.getChild(element, childIndex); - } catch (Exception e) { - return null; - } - - if (element == null) { - return null; - } - - } - } - - return element; + super(client); } - - /** - * Generates a String locator using domChild[x] parts for the element - * relative to the baseElement. - * - * @param element - * The target element - * @param baseElement - * The starting point for the locator. The generated path is - * relative to this element. - * @return A String locator that can be used to locate the target element - * using {@link #getElementByDOMPath(Element, String)} or null if - * the locator String cannot be created. - */ - private String getDOMPathForElement(Element element, Element baseElement) { - Element e = element; - String path = ""; - while (true) { - int childIndex = -1; - Element siblingIterator = e; - while (siblingIterator != null) { - childIndex++; - siblingIterator = siblingIterator.getPreviousSiblingElement() - .cast(); - } - - path = PARENTCHILD_SEPARATOR + "domChild[" + childIndex + "]" - + path; - - JavaScriptObject parent = e.getParentElement(); - if (parent == null) { - return null; - } - // The parent check is a work around for Firefox 15 which fails to - // compare elements properly (#9534) - if (parent == baseElement) { - break; - } - - e = parent.cast(); - } - - return path; - } - - /** - * Locates an element using a String locator (path) which identifies a DOM - * element. The {@link #getPathForElement(Element)} method can be used for - * the inverse operation, i.e. generating a string expression for a DOM - * element. - * - * @since 5.4 - * @param path - * The String locater which identifies the target element. - * @return The DOM element identified by {@code path} or null if the element - * could not be located. - */ - public Element getElementByPath(String path) { - /* - * Path is of type "targetWidgetPath#componentPart" or - * "targetWidgetPath". - */ - String parts[] = path.split(SUBPART_SEPARATOR, 2); - String widgetPath = parts[0]; - Widget w = getWidgetFromPath(widgetPath); - if (w == null || !Util.isAttachedAndDisplayed(w)) { - return null; - } - - if (parts.length == 1) { - int pos = widgetPath.indexOf("domChild"); - if (pos == -1) { - return w.getElement(); - } - - // Contains dom reference to a sub element of the widget - String subPath = widgetPath.substring(pos); - return getElementByDOMPath(w.getElement(), subPath); - } else if (parts.length == 2) { - if (w instanceof SubPartAware) { - return ((SubPartAware) w).getSubPartElement(parts[1]); - } - } - - return null; - } - - /** - * Creates a locator String for the given widget. The path can be used to - * locate the widget using {@link #getWidgetFromPath(String)}. - * - * Returns null if no path can be determined for the widget or if the widget - * is null. - * - * @param w - * The target widget - * @return A String locator for the widget - */ - private String getPathForWidget(Widget w) { - if (w == null) { - return null; - } - String elementId = w.getElement().getId(); - if (elementId != null && !elementId.isEmpty() - && !elementId.startsWith("gwt-uid-")) { - // Use PID_S+id if the user has set an id but do not use it for auto - // generated id:s as these might not be consistent - return "PID_S" + elementId; - } else if (w instanceof VUI) { - return ""; - } else if (w instanceof VWindow) { - Connector windowConnector = ConnectorMap.get(client) - .getConnector(w); - List<WindowConnector> subWindowList = client.getUIConnector() - .getSubWindows(); - int indexOfSubWindow = subWindowList.indexOf(windowConnector); - return PARENTCHILD_SEPARATOR + "VWindow[" + indexOfSubWindow + "]"; - } else if (w instanceof RootPanel) { - return ROOT_ID; - } - - Widget parent = w.getParent(); - - String basePath = getPathForWidget(parent); - if (basePath == null) { - return null; - } - String simpleName = Util.getSimpleName(w); - - /* - * Check if the parent implements Iterable. At least VPopupView does not - * implement HasWdgets so we cannot check for that. - */ - if (!(parent instanceof Iterable<?>)) { - // Parent does not implement Iterable so we cannot find out which - // child this is - return null; - } - - Iterator<?> i = ((Iterable<?>) parent).iterator(); - int pos = 0; - while (i.hasNext()) { - Object child = i.next(); - if (child == w) { - return basePath + PARENTCHILD_SEPARATOR + simpleName + "[" - + pos + "]"; - } - String simpleName2 = Util.getSimpleName(child); - if (simpleName.equals(simpleName2)) { - pos++; - } - } - - return null; - } - - /** - * Locates the widget based on a String locator. - * - * @param path - * The String locator that identifies the widget. - * @return The Widget identified by the String locator or null if the widget - * could not be identified. - */ - private Widget getWidgetFromPath(String path) { - Widget w = null; - String parts[] = path.split(PARENTCHILD_SEPARATOR); - - for (int i = 0; i < parts.length; i++) { - String part = parts[i]; - - if (part.equals(ROOT_ID)) { - w = RootPanel.get(); - } else if (part.equals("")) { - w = client.getUIConnector().getWidget(); - } else if (w == null) { - String id = part; - // Must be old static pid (PID_S*) - ServerConnector connector = ConnectorMap.get(client) - .getConnector(id); - if (connector == null) { - // Lookup by component id - // TODO Optimize this - connector = findConnectorById(client.getUIConnector(), - id.substring(5)); - } - - if (connector instanceof ComponentConnector) { - w = ((ComponentConnector) connector).getWidget(); - } else { - // Not found - return null; - } - } else if (part.startsWith("domChild[")) { - // The target widget has been found and the rest identifies the - // element - break; - } else if (w instanceof Iterable) { - // W identifies a widget that contains other widgets, as it - // should. Try to locate the child - Iterable<?> parent = (Iterable<?>) w; - - // Part is of type "VVerticalLayout[0]", split this into - // VVerticalLayout and 0 - String[] split = part.split("\\[", 2); - String widgetClassName = split[0]; - String indexString = split[1].substring(0, - split[1].length() - 1); - int widgetPosition = Integer.parseInt(indexString); - - // AbsolutePanel in GridLayout has been removed -> skip it - if (w instanceof VGridLayout - && "AbsolutePanel".equals(widgetClassName)) { - continue; - } - - // FlowPane in CSSLayout has been removed -> skip it - if (w instanceof VCssLayout - && "VCssLayout$FlowPane".equals(widgetClassName)) { - continue; - } - - // ChildComponentContainer and VOrderedLayout$Slot have been - // replaced with Slot - if (w instanceof VAbstractOrderedLayout - && ("ChildComponentContainer".equals(widgetClassName) || "VOrderedLayout$Slot" - .equals(widgetClassName))) { - widgetClassName = "Slot"; - } - - if (w instanceof VTabsheetPanel && widgetPosition != 0) { - // TabSheetPanel now only contains 1 connector => the index - // is always 0 which indicates the widget in the active tab - widgetPosition = 0; - } - if (w instanceof VOverlay - && "VCalendarPanel".equals(widgetClassName)) { - // Vaadin 7.1 adds a wrapper for datefield popups - parent = (Iterable<?>) ((Iterable) parent).iterator() - .next(); - } - /* - * The new grid and ordered layotus do not contain - * ChildComponentContainer widgets. This is instead simulated by - * constructing a path step that would find the desired widget - * from the layout and injecting it as the next search step - * (which would originally have found the widget inside the - * ChildComponentContainer) - */ - if ((w instanceof VGridLayout) - && "ChildComponentContainer".equals(widgetClassName) - && i + 1 < parts.length) { - - HasWidgets layout = (HasWidgets) w; - - String nextPart = parts[i + 1]; - String[] nextSplit = nextPart.split("\\[", 2); - String nextWidgetClassName = nextSplit[0]; - - // Find the n:th child and count the number of children with - // the same type before it - int nextIndex = 0; - for (Widget child : layout) { - boolean matchingType = nextWidgetClassName.equals(Util - .getSimpleName(child)); - if (matchingType && widgetPosition == 0) { - // This is the n:th child that we looked for - break; - } else if (widgetPosition < 0) { - // Error if we're past the desired position without - // a match - return null; - } else if (matchingType) { - // If this was another child of the expected type, - // increase the count for the next step - nextIndex++; - } - - // Don't count captions - if (!(child instanceof VCaption)) { - widgetPosition--; - } - } - - // Advance to the next step, this time checking for the - // actual child widget - parts[i + 1] = nextWidgetClassName + '[' + nextIndex + ']'; - continue; - } - - // Locate the child - Iterator<? extends Widget> iterator; - - /* - * VWindow and VContextMenu workarounds for backwards - * compatibility - */ - if (widgetClassName.equals("VWindow")) { - List<WindowConnector> windows = client.getUIConnector() - .getSubWindows(); - List<VWindow> windowWidgets = new ArrayList<VWindow>( - windows.size()); - for (WindowConnector wc : windows) { - windowWidgets.add(wc.getWidget()); - } - iterator = windowWidgets.iterator(); - } else if (widgetClassName.equals("VContextMenu")) { - return client.getContextMenu(); - } else { - iterator = (Iterator<? extends Widget>) parent.iterator(); - } - - boolean ok = false; - - // Find the widgetPosition:th child of type "widgetClassName" - while (iterator.hasNext()) { - - Widget child = iterator.next(); - String simpleName2 = Util.getSimpleName(child); - - if (!widgetClassName.equals(simpleName2) - && child instanceof Slot) { - /* - * Support legacy tests without any selector for the - * Slot widget (i.e. /VVerticalLayout[0]/VButton[0]) by - * directly checking the stuff inside the slot - */ - child = ((Slot) child).getWidget(); - simpleName2 = Util.getSimpleName(child); - } - - if (widgetClassName.equals(simpleName2)) { - if (widgetPosition == 0) { - w = child; - ok = true; - break; - } - widgetPosition--; - - } - } - - if (!ok) { - // Did not find the child - return null; - } - } else { - // W identifies something that is not a "HasWidgets". This - // should not happen as all widget containers should implement - // HasWidgets. - return null; - } - } - - return w; - } - - private ServerConnector findConnectorById(ServerConnector root, String id) { - SharedState state = root.getState(); - if (state instanceof AbstractComponentState - && id.equals(((AbstractComponentState) state).id)) { - return root; - } - for (ServerConnector child : root.getChildren()) { - ServerConnector found = findConnectorById(child, id); - if (found != null) { - return found; - } - } - - return null; - } - } diff --git a/client/src/com/vaadin/client/ConnectorMap.java b/client/src/com/vaadin/client/ConnectorMap.java index 810f12824a..c2f1eda21d 100644 --- a/client/src/com/vaadin/client/ConnectorMap.java +++ b/client/src/com/vaadin/client/ConnectorMap.java @@ -116,7 +116,7 @@ public class ConnectorMap { * no connector was found */ public ComponentConnector getConnector(Widget widget) { - return getConnector(widget.getElement()); + return widget == null ? null : getConnector(widget.getElement()); } public void registerConnector(String id, ServerConnector connector) { diff --git a/client/src/com/vaadin/client/Profiler.java b/client/src/com/vaadin/client/Profiler.java index 083f2559b1..cfce59b08b 100644 --- a/client/src/com/vaadin/client/Profiler.java +++ b/client/src/com/vaadin/client/Profiler.java @@ -297,10 +297,6 @@ public class Profiler { if (isEnabled()) { double now = Duration.currentTimeMillis(); - StringBuilder stringBuilder = new StringBuilder( - "Time since window.performance.timing events"); - SimpleTree tree = new SimpleTree(stringBuilder.toString()); - String[] keys = new String[] { "navigationStart", "unloadEventStart", "unloadEventEnd", "redirectStart", "redirectEnd", "fetchStart", "domainLookupStart", diff --git a/client/src/com/vaadin/client/SimpleTree.java b/client/src/com/vaadin/client/SimpleTree.java index 7370496cb8..edfa23fb13 100644 --- a/client/src/com/vaadin/client/SimpleTree.java +++ b/client/src/com/vaadin/client/SimpleTree.java @@ -116,6 +116,14 @@ public class SimpleTree extends ComplexPanel implements HasDoubleClickHandlers { } } + public boolean isOpen() { + return "-".equals(handle.getInnerHTML()); + } + + public String getCaption() { + return text.getInnerText(); + } + public SimpleTree(String caption) { this(); setText(caption); diff --git a/client/src/com/vaadin/client/Util.java b/client/src/com/vaadin/client/Util.java index 8972670232..edbb40e86c 100644 --- a/client/src/com/vaadin/client/Util.java +++ b/client/src/com/vaadin/client/Util.java @@ -855,6 +855,7 @@ public class Util { * @param class1 * the Widget type to seek for */ + @SuppressWarnings("unchecked") public static <T> T findWidget(Element element, Class<? extends Widget> class1) { if (element != null) { @@ -866,7 +867,7 @@ public class Util { element = (Element) element.getParentElement(); } } - if (eventListener != null) { + if (eventListener instanceof Widget) { /* * Then find the first widget of type class1 from widget * hierarchy diff --git a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java index c9b9e46cd5..9eb2b881bb 100644 --- a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java +++ b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java @@ -344,6 +344,14 @@ public class AtmospherePushConnection implements PushConnection { state = State.CONNECT_PENDING; } + protected void onClientTimeout(AtmosphereResponse response) { + state = State.DISCONNECTED; + errorHandler + .onError( + "Client unexpectedly disconnected. Ensure client timeout is disabled.", + -1); + } + protected void onReconnect(JavaScriptObject request, final AtmosphereResponse response) { if (state == State.CONNECTED) { @@ -438,6 +446,7 @@ public class AtmospherePushConnection implements PushConnection { fallbackTransport: 'streaming', contentType: 'application/json; charset=UTF-8', reconnectInterval: 5000, + timeout: -1, maxReconnectOnClose: 10000000, trackMessageLength: true, enableProtocol: false, @@ -472,6 +481,9 @@ public class AtmospherePushConnection implements PushConnection { config.onReconnect = $entry(function(request, response) { self.@com.vaadin.client.communication.AtmospherePushConnection::onReconnect(*)(request, response); }); + config.onClientTimeout = $entry(function(request) { + self.@com.vaadin.client.communication.AtmospherePushConnection::onClientTimeout(*)(request); + }); return $wnd.jQueryVaadin.atmosphere.subscribe(config); }-*/; diff --git a/client/src/com/vaadin/client/communication/Date_Serializer.java b/client/src/com/vaadin/client/communication/Date_Serializer.java new file mode 100644 index 0000000000..c6eb7af188 --- /dev/null +++ b/client/src/com/vaadin/client/communication/Date_Serializer.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.communication; + +import java.util.Date; + +import com.google.gwt.json.client.JSONNumber; +import com.google.gwt.json.client.JSONValue; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.metadata.Type; + +/** + * Client side serializer/deserializer for java.util.Date + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class Date_Serializer implements JSONSerializer<Date> { + + @Override + public Date deserialize(Type type, JSONValue jsonValue, + ApplicationConnection connection) { + return new Date((long) ((JSONNumber) jsonValue).doubleValue()); + } + + @Override + public JSONValue serialize(Date value, ApplicationConnection connection) { + return new JSONNumber(value.getTime()); + } + +} diff --git a/client/src/com/vaadin/client/communication/Heartbeat.java b/client/src/com/vaadin/client/communication/Heartbeat.java new file mode 100644 index 0000000000..4b80827127 --- /dev/null +++ b/client/src/com/vaadin/client/communication/Heartbeat.java @@ -0,0 +1,171 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.communication; + +import java.util.logging.Logger; + +import com.google.gwt.http.client.Request; +import com.google.gwt.http.client.RequestBuilder; +import com.google.gwt.http.client.RequestCallback; +import com.google.gwt.http.client.RequestException; +import com.google.gwt.http.client.Response; +import com.google.gwt.user.client.Timer; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent; +import com.vaadin.shared.ApplicationConstants; +import com.vaadin.shared.ui.ui.UIConstants; + +/** + * Handles sending of heartbeats to the server and reacting to the response + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class Heartbeat { + + private int interval = -1; + private Timer timer = new Timer() { + @Override + public void run() { + send(); + } + }; + + private ApplicationConnection connection; + + private static Logger getLogger() { + return Logger.getLogger(Heartbeat.class.getName()); + } + + /** + * Initializes the heartbeat for the given application connection + * + * @param connection + * the connection + */ + public void init(ApplicationConnection connection) { + this.connection = connection; + interval = connection.getConfiguration().getHeartbeatInterval(); + setInterval(interval); + schedule(); + + connection.addHandler( + ApplicationConnection.ApplicationStoppedEvent.TYPE, + new ApplicationConnection.ApplicationStoppedHandler() { + + @Override + public void onApplicationStopped( + ApplicationStoppedEvent event) { + setInterval(-1); + schedule(); + } + }); + + } + + /** + * Sends a heartbeat to the server + */ + public void send() { + final String uri = ApplicationConnection.addGetParameters( + getConnection().translateVaadinUri( + ApplicationConstants.APP_PROTOCOL_PREFIX + + ApplicationConstants.HEARTBEAT_PATH + '/'), + UIConstants.UI_ID_PARAMETER + "=" + + getConnection().getConfiguration().getUIId()); + + final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri); + + final RequestCallback callback = new RequestCallback() { + + @Override + public void onResponseReceived(Request request, Response response) { + int status = response.getStatusCode(); + if (status == Response.SC_OK) { + // TODO Permit retry in some error situations + getLogger().fine("Heartbeat response OK"); + schedule(); + } else if (status == Response.SC_GONE) { + // FIXME This should really do something else like send an + // event + getConnection().showSessionExpiredError(null); + } else { + getLogger().warning( + "Failed sending heartbeat to server. Error code: " + + status); + } + } + + @Override + public void onError(Request request, Throwable exception) { + getLogger().severe("Exception sending heartbeat: " + exception); + } + }; + + rb.setCallback(callback); + + try { + getLogger().fine("Sending heartbeat request..."); + rb.send(); + } catch (RequestException re) { + callback.onError(null, re); + } + + } + + /** + * @return the interval at which heartbeat requests are sent + */ + public int getInterval() { + return interval; + } + + /** + * sets the interval at which heartbeat requests are sent + * + * @param interval + * the new interval + */ + public void setInterval(int interval) { + this.interval = interval; + } + + /** + * Updates the schedule of the heartbeat to match the set interval. A + * negative interval disables the heartbeat. + */ + public void schedule() { + if (getInterval() > 0) { + getLogger() + .fine("Scheduling heartbeat in " + interval + " seconds"); + timer.schedule(interval * 1000); + } else { + if (timer != null) { + getLogger().fine("Disabling heartbeat"); + timer.cancel(); + } + } + + } + + /** + * @return the application connection + */ + protected ApplicationConnection getConnection() { + return connection; + } + +} diff --git a/client/src/com/vaadin/client/communication/JSONSerializer.java b/client/src/com/vaadin/client/communication/JSONSerializer.java index e5829ece24..a4e78e503c 100644 --- a/client/src/com/vaadin/client/communication/JSONSerializer.java +++ b/client/src/com/vaadin/client/communication/JSONSerializer.java @@ -23,14 +23,17 @@ import com.vaadin.client.metadata.Type; /** * Implementors of this interface knows how to serialize an Object of a given * type to JSON and how to deserialize the JSON back into an object. - * + * <p> * The {@link #serialize(Object, ApplicationConnection)} and * {@link #deserialize(Type, JSONValue, ApplicationConnection)} methods must be * symmetric so they can be chained and produce the original result (or an equal * result). - * + * <p> * Each {@link JSONSerializer} implementation can handle an object of a single * type - see {@link Type#findSerializer()}. + * <p> + * This is the client side interface, see + * com.vaadin.server.communication.JSONSerializer for the server side interface. * * @since 7.0 */ diff --git a/client/src/com/vaadin/client/componentlocator/ComponentLocator.java b/client/src/com/vaadin/client/componentlocator/ComponentLocator.java new file mode 100644 index 0000000000..d2a89c00d5 --- /dev/null +++ b/client/src/com/vaadin/client/componentlocator/ComponentLocator.java @@ -0,0 +1,220 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.componentlocator; + +import java.util.Arrays; +import java.util.List; + +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.client.JsArray; +import com.google.gwt.user.client.Element; +import com.vaadin.client.ApplicationConnection; + +/** + * ComponentLocator provides methods for generating a String locator for a given + * DOM element and for locating a DOM element using a String locator. + * <p> + * The main use for this class is locating components for automated testing + * purposes. + * + * @since 7.2, moved from {@link com.vaadin.client.ComponentLocator} + */ +public class ComponentLocator { + + private final List<LocatorStrategy> locatorStrategies; + + /** + * Reference to ApplicationConnection instance. + */ + + private final ApplicationConnection client; + + /** + * Construct a ComponentLocator for the given ApplicationConnection. + * + * @param client + * ApplicationConnection instance for the application. + */ + public ComponentLocator(ApplicationConnection client) { + this.client = client; + locatorStrategies = Arrays.asList(new VaadinFinderLocatorStrategy( + client), new LegacyLocatorStrategy(client)); + } + + /** + * Generates a String locator which uniquely identifies the target element. + * The {@link #getElementByPath(String)} method can be used for the inverse + * operation, i.e. locating an element based on the return value from this + * method. + * <p> + * Note that getElementByPath(getPathForElement(element)) == element is not + * always true as #getPathForElement(Element) can return a path to another + * element if the widget determines an action on the other element will give + * the same result as the action on the target element. + * </p> + * + * @since 5.4 + * @param targetElement + * The element to generate a path for. + * @return A String locator that identifies the target element or null if a + * String locator could not be created. + */ + public String getPathForElement(Element targetElement) { + for (LocatorStrategy strategy : locatorStrategies) { + String path = strategy.getPathForElement(targetElement); + if (null != path) { + return path; + } + } + return null; + } + + /** + * Locates an element using a String locator (path) which identifies a DOM + * element. The {@link #getPathForElement(Element)} method can be used for + * the inverse operation, i.e. generating a string expression for a DOM + * element. + * + * @since 5.4 + * @param path + * The String locator which identifies the target element. + * @return The DOM element identified by {@code path} or null if the element + * could not be located. + */ + public Element getElementByPath(String path) { + for (LocatorStrategy strategy : locatorStrategies) { + if (strategy.validatePath(path)) { + Element element = strategy.getElementByPath(path); + if (null != element) { + return element; + } + } + } + return null; + } + + /** + * Locates elements using a String locator (path) which identifies DOM + * elements. + * + * @since 7.2 + * @param path + * The String locator which identifies target elements. + * @return The JavaScriptArray of DOM elements identified by {@code path} or + * empty array if elements could not be located. + */ + public JsArray<Element> getElementsByPath(String path) { + JsArray<Element> jsElements = JavaScriptObject.createArray().cast(); + for (LocatorStrategy strategy : locatorStrategies) { + if (strategy.validatePath(path)) { + List<Element> elements = strategy.getElementsByPath(path); + if (elements.size() > 0) { + for (Element e : elements) { + jsElements.push(e); + } + return jsElements; + } + } + } + return jsElements; + } + + /** + * Locates elements using a String locator (path) which identifies DOM + * elements. The path starts from the specified root element. + * + * @see #getElementByPath(String) + * + * @since 7.2 + * @param path + * The path of elements to be found + * @param root + * The root element where the path is anchored + * @return The JavaScriptArray of DOM elements identified by {@code path} or + * empty array if elements could not be located. + */ + public JsArray<Element> getElementsByPathStartingAt(String path, + Element root) { + JsArray<Element> jsElements = JavaScriptObject.createArray().cast(); + for (LocatorStrategy strategy : locatorStrategies) { + if (strategy.validatePath(path)) { + List<Element> elements = strategy.getElementsByPathStartingAt( + path, root); + if (elements.size() > 0) { + for (Element e : elements) { + jsElements.push(e); + } + return jsElements; + } + } + } + return jsElements; + } + + /** + * Locates an element using a String locator (path) which identifies a DOM + * element. The path starts from the specified root element. + * + * @see #getElementByPath(String) + * + * @param path + * The path of the element to be found + * @param root + * The root element where the path is anchored + * @return The DOM element identified by {@code path} or null if the element + * could not be located. + */ + public Element getElementByPathStartingAt(String path, Element root) { + for (LocatorStrategy strategy : locatorStrategies) { + if (strategy.validatePath(path)) { + Element element = strategy.getElementByPathStartingAt(path, + root); + if (null != element) { + return element; + } + } + } + return null; + } + + /** + * Returns the {@link ApplicationConnection} used by this locator. + * <p> + * This method is primarily for internal use by the framework. + * + * @return the application connection + */ + public ApplicationConnection getClient() { + return client; + } + + /** + * Check if a given selector is valid for LegacyLocatorStrategy. + * + * @param path + * Vaadin selector path + * @return true if passes path validation with LegacyLocatorStrategy + */ + public boolean isValidForLegacyLocator(String path) { + for (LocatorStrategy ls : locatorStrategies) { + if (ls instanceof LegacyLocatorStrategy) { + return ls.validatePath(path); + } + } + return false; + } + +} diff --git a/client/src/com/vaadin/client/componentlocator/LegacyLocatorStrategy.java b/client/src/com/vaadin/client/componentlocator/LegacyLocatorStrategy.java new file mode 100644 index 0000000000..2e9d0a16d0 --- /dev/null +++ b/client/src/com/vaadin/client/componentlocator/LegacyLocatorStrategy.java @@ -0,0 +1,719 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.componentlocator; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.regexp.shared.RegExp; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.HasWidgets; +import com.google.gwt.user.client.ui.RootPanel; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ConnectorMap; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.Util; +import com.vaadin.client.VCaption; +import com.vaadin.client.ui.SubPartAware; +import com.vaadin.client.ui.VCssLayout; +import com.vaadin.client.ui.VGridLayout; +import com.vaadin.client.ui.VOverlay; +import com.vaadin.client.ui.VTabsheetPanel; +import com.vaadin.client.ui.VUI; +import com.vaadin.client.ui.VWindow; +import com.vaadin.client.ui.orderedlayout.Slot; +import com.vaadin.client.ui.orderedlayout.VAbstractOrderedLayout; +import com.vaadin.client.ui.window.WindowConnector; +import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.Connector; +import com.vaadin.shared.communication.SharedState; + +/** + * The LegacyLocatorStrategy class handles the legacy locator syntax that was + * introduced in version 5.4 of the framework. The legacy locator strategy is + * always used if no other strategy claims responsibility for a locator string. + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class LegacyLocatorStrategy implements LocatorStrategy { + + /** + * Separator used in the String locator between a parent and a child widget. + */ + static final String PARENTCHILD_SEPARATOR = "/"; + /** + * Separator used in the String locator between the part identifying the + * containing widget and the part identifying the target element within the + * widget. + */ + static final String SUBPART_SEPARATOR = "#"; + /** + * String that identifies the root panel when appearing first in the String + * locator. + */ + static final String ROOT_ID = "Root"; + + private final ApplicationConnection client; + + private static final RegExp validSyntax = RegExp + .compile("^((\\w+::)?((PID_S)?\\w[-$_a-zA-Z0-9.' ]*)?)?(/[-$_a-zA-Z0-9]+\\[\\d+\\])*/?(#.*)?$"); + + public LegacyLocatorStrategy(ApplicationConnection clientConnection) { + client = clientConnection; + } + + @Override + public boolean validatePath(String path) { + return validSyntax.test(path); + } + + @Override + public String getPathForElement(Element targetElement) { + ComponentConnector connector = Util + .findPaintable(client, targetElement); + + Widget w = null; + if (connector != null) { + // If we found a Paintable then we use that as reference. We should + // find the Paintable for all but very special cases (like + // overlays). + w = connector.getWidget(); + + /* + * Still if the Paintable contains a widget that implements + * SubPartAware, we want to use that as a reference + */ + Widget targetParent = findParentWidget(targetElement, w); + while (targetParent != w && targetParent != null) { + if (targetParent instanceof SubPartAware) { + /* + * The targetParent widget is a child of the Paintable and + * the first parent (of the targetElement) that implements + * SubPartAware + */ + w = targetParent; + break; + } + targetParent = targetParent.getParent(); + } + } + if (w == null) { + // Check if the element is part of a widget that is attached + // directly to the root panel + RootPanel rootPanel = RootPanel.get(); + int rootWidgetCount = rootPanel.getWidgetCount(); + for (int i = 0; i < rootWidgetCount; i++) { + Widget rootWidget = rootPanel.getWidget(i); + if (rootWidget.getElement().isOrHasChild(targetElement)) { + // The target element is contained by this root widget + w = findParentWidget(targetElement, rootWidget); + break; + } + } + if (w != null) { + // We found a widget but we should still see if we find a + // SubPartAware implementor (we cannot find the Paintable as + // there is no link from VOverlay to its paintable/owner). + Widget subPartAwareWidget = findSubPartAwareParentWidget(w); + if (subPartAwareWidget != null) { + w = subPartAwareWidget; + } + } + } + + if (w == null) { + // Containing widget not found + return null; + } + + // Determine the path for the target widget + String path = getPathForWidget(w); + if (path == null) { + /* + * No path could be determined for the target widget. Cannot create + * a locator string. + */ + return null; + } + + // The parent check is a work around for Firefox 15 which fails to + // compare elements properly (#9534) + if (w.getElement() == targetElement) { + /* + * We are done if the target element is the root of the target + * widget. + */ + return path; + } else if (w instanceof SubPartAware) { + /* + * If the widget can provide an identifier for the targetElement we + * let it do that + */ + String elementLocator = ((SubPartAware) w) + .getSubPartName(targetElement); + if (elementLocator != null) { + return path + LegacyLocatorStrategy.SUBPART_SEPARATOR + + elementLocator; + } + } + /* + * If everything else fails we use the DOM path to identify the target + * element + */ + String domPath = getDOMPathForElement(targetElement, w.getElement()); + if (domPath == null) { + return path; + } else { + return path + domPath; + } + } + + /** + * {@inheritDoc} + */ + @Override + public Element getElementByPath(String path) { + return getElementByPathStartingAt(path, null); + } + + /** + * {@inheritDoc} + */ + @Override + public Element getElementByPathStartingAt(String path, Element baseElement) { + /* + * Path is of type "targetWidgetPath#componentPart" or + * "targetWidgetPath". + */ + String parts[] = path.split(LegacyLocatorStrategy.SUBPART_SEPARATOR, 2); + String widgetPath = parts[0]; + + // Note that this only works if baseElement can be mapped to a + // widget to which the path is relative. Otherwise, the current + // implementation simply interprets the path as if baseElement was + // null. + Widget baseWidget = Util.findWidget(baseElement, null); + + Widget w = getWidgetFromPath(widgetPath, baseWidget); + if (w == null || !Util.isAttachedAndDisplayed(w)) { + return null; + } + if (parts.length == 1) { + int pos = widgetPath.indexOf("domChild"); + if (pos == -1) { + return w.getElement(); + } + + // Contains dom reference to a sub element of the widget + String subPath = widgetPath.substring(pos); + return getElementByDOMPath(w.getElement(), subPath); + } else if (parts.length == 2) { + if (w instanceof SubPartAware) { + return ((SubPartAware) w).getSubPartElement(parts[1]); + } + } + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public List<Element> getElementsByPath(String path) { + // This type of search is not supported in LegacyLocator + List<Element> array = new ArrayList<Element>(); + Element e = getElementByPath(path); + if (e != null) { + array.add(e); + } + return array; + } + + /** + * {@inheritDoc} + */ + @Override + public List<Element> getElementsByPathStartingAt(String path, Element root) { + // This type of search is not supported in LegacyLocator + List<Element> array = new ArrayList<Element>(); + Element e = getElementByPathStartingAt(path, root); + if (e != null) { + array.add(e); + } + return array; + } + + /** + * Finds the first widget in the hierarchy (moving upwards) that implements + * SubPartAware. Returns the SubPartAware implementor or null if none is + * found. + * + * @param w + * The widget to start from. This is returned if it implements + * SubPartAware. + * @return The first widget (upwards in hierarchy) that implements + * SubPartAware or null + */ + Widget findSubPartAwareParentWidget(Widget w) { + + while (w != null) { + if (w instanceof SubPartAware) { + return w; + } + w = w.getParent(); + } + return null; + } + + /** + * Returns the first widget found when going from {@code targetElement} + * upwards in the DOM hierarchy, assuming that {@code ancestorWidget} is a + * parent of {@code targetElement}. + * + * @param targetElement + * @param ancestorWidget + * @return The widget whose root element is a parent of + * {@code targetElement}. + */ + private Widget findParentWidget(Element targetElement, Widget ancestorWidget) { + /* + * As we cannot resolve Widgets from the element we start from the + * widget and move downwards to the correct child widget, as long as we + * find one. + */ + if (ancestorWidget instanceof HasWidgets) { + for (Widget w : ((HasWidgets) ancestorWidget)) { + if (w.getElement().isOrHasChild(targetElement)) { + return findParentWidget(targetElement, w); + } + } + } + + // No children found, this is it + return ancestorWidget; + } + + /** + * Locates an element based on a DOM path and a base element. + * + * @param baseElement + * The base element which the path is relative to + * @param path + * String locator (consisting of domChild[x] parts) that + * identifies the element + * @return The element identified by path, relative to baseElement or null + * if the element could not be found. + */ + private Element getElementByDOMPath(Element baseElement, String path) { + String parts[] = path.split(PARENTCHILD_SEPARATOR); + Element element = baseElement; + + for (int i = 0, l = parts.length; i < l; ++i) { + String part = parts[i]; + if (part.startsWith("domChild[")) { + String childIndexString = part.substring("domChild[".length(), + part.length() - 1); + + if (Util.findWidget(baseElement, null) instanceof VAbstractOrderedLayout) { + if (element.hasChildNodes()) { + Element e = element.getFirstChildElement().cast(); + String cn = e.getClassName(); + if (cn != null + && (cn.equals("v-expand") || cn + .contains("v-has-caption"))) { + element = e; + } + } + } + + try { + int childIndex = Integer.parseInt(childIndexString); + element = DOM.getChild(element, childIndex); + } catch (Exception e) { + return null; + } + + if (element == null) { + return null; + } + + } else { + + path = parts[i]; + for (int j = i + 1; j < l; ++j) { + path += PARENTCHILD_SEPARATOR + parts[j]; + } + + return getElementByPathStartingAt(path, element); + } + } + + return element; + } + + /** + * Generates a String locator using domChild[x] parts for the element + * relative to the baseElement. + * + * @param element + * The target element + * @param baseElement + * The starting point for the locator. The generated path is + * relative to this element. + * @return A String locator that can be used to locate the target element + * using + * {@link #getElementByDOMPath(com.google.gwt.user.client.Element, String)} + * or null if the locator String cannot be created. + */ + private String getDOMPathForElement(Element element, Element baseElement) { + Element e = element; + String path = ""; + while (true) { + int childIndex = -1; + Element siblingIterator = e; + while (siblingIterator != null) { + childIndex++; + siblingIterator = siblingIterator.getPreviousSiblingElement() + .cast(); + } + + path = PARENTCHILD_SEPARATOR + "domChild[" + childIndex + "]" + + path; + + JavaScriptObject parent = e.getParentElement(); + if (parent == null) { + return null; + } + // The parent check is a work around for Firefox 15 which fails to + // compare elements properly (#9534) + if (parent == baseElement) { + break; + } + + e = parent.cast(); + } + + return path; + } + + /** + * Creates a locator String for the given widget. The path can be used to + * locate the widget using {@link #getWidgetFromPath(String, Widget)}. + * <p/> + * Returns null if no path can be determined for the widget or if the widget + * is null. + * + * @param w + * The target widget + * @return A String locator for the widget + */ + private String getPathForWidget(Widget w) { + if (w == null) { + return null; + } + String elementId = w.getElement().getId(); + if (elementId != null && !elementId.isEmpty() + && !elementId.startsWith("gwt-uid-")) { + // Use PID_S+id if the user has set an id but do not use it for auto + // generated id:s as these might not be consistent + return "PID_S" + elementId; + } else if (w instanceof VUI) { + return ""; + } else if (w instanceof VWindow) { + Connector windowConnector = ConnectorMap.get(client) + .getConnector(w); + List<WindowConnector> subWindowList = client.getUIConnector() + .getSubWindows(); + int indexOfSubWindow = subWindowList.indexOf(windowConnector); + return PARENTCHILD_SEPARATOR + "VWindow[" + indexOfSubWindow + "]"; + } else if (w instanceof RootPanel) { + return ROOT_ID; + } + + Widget parent = w.getParent(); + + String basePath = getPathForWidget(parent); + if (basePath == null) { + return null; + } + String simpleName = Util.getSimpleName(w); + + /* + * Check if the parent implements Iterable. At least VPopupView does not + * implement HasWdgets so we cannot check for that. + */ + if (!(parent instanceof Iterable<?>)) { + // Parent does not implement Iterable so we cannot find out which + // child this is + return null; + } + + Iterator<?> i = ((Iterable<?>) parent).iterator(); + int pos = 0; + while (i.hasNext()) { + Object child = i.next(); + if (child == w) { + return basePath + PARENTCHILD_SEPARATOR + simpleName + "[" + + pos + "]"; + } + String simpleName2 = Util.getSimpleName(child); + if (simpleName.equals(simpleName2)) { + pos++; + } + } + + return null; + } + + /** + * Locates the widget based on a String locator. + * + * @param path + * The String locator that identifies the widget. + * @param baseWidget + * the widget to which the path is relative, null if relative to + * root + * @return The Widget identified by the String locator or null if the widget + * could not be identified. + */ + @SuppressWarnings("unchecked") + private Widget getWidgetFromPath(String path, Widget baseWidget) { + Widget w = baseWidget; + String parts[] = path.split(PARENTCHILD_SEPARATOR); + + for (int i = 0; i < parts.length; i++) { + String part = parts[i]; + + if (part.equals(ROOT_ID)) { + w = RootPanel.get(); + } else if (part.equals("")) { + if (w == null) { + w = client.getUIConnector().getWidget(); + } + } else if (w == null) { + String id = part; + // Must be old static pid (PID_S*) + ServerConnector connector = ConnectorMap.get(client) + .getConnector(id); + if (connector == null) { + // Lookup by component id + // TODO Optimize this + connector = findConnectorById(client.getUIConnector(), + id.substring(5)); + } + + if (connector instanceof ComponentConnector) { + w = ((ComponentConnector) connector).getWidget(); + } else { + // Not found + return null; + } + } else if (part.startsWith("domChild[")) { + // The target widget has been found and the rest identifies the + // element + break; + } else if (w instanceof Iterable) { + // W identifies a widget that contains other widgets, as it + // should. Try to locate the child + Iterable<?> parent = (Iterable<?>) w; + + // Part is of type "VVerticalLayout[0]", split this into + // VVerticalLayout and 0 + String[] split = part.split("\\[", 2); + String widgetClassName = split[0]; + String indexString = split[1].substring(0, + split[1].length() - 1); + + int widgetPosition; + try { + widgetPosition = Integer.parseInt(indexString); + } catch (NumberFormatException e) { + // We've probably been fed a new-style Vaadin locator with a + // string-form predicate, that doesn't match anything in the + // search space. + return null; + } + + // AbsolutePanel in GridLayout has been removed -> skip it + if (w instanceof VGridLayout + && "AbsolutePanel".equals(widgetClassName)) { + continue; + } + + // FlowPane in CSSLayout has been removed -> skip it + if (w instanceof VCssLayout + && "VCssLayout$FlowPane".equals(widgetClassName)) { + continue; + } + + // ChildComponentContainer and VOrderedLayout$Slot have been + // replaced with Slot + if (w instanceof VAbstractOrderedLayout + && ("ChildComponentContainer".equals(widgetClassName) || "VOrderedLayout$Slot" + .equals(widgetClassName))) { + widgetClassName = "Slot"; + } + + if (w instanceof VTabsheetPanel && widgetPosition != 0) { + // TabSheetPanel now only contains 1 connector => the index + // is always 0 which indicates the widget in the active tab + widgetPosition = 0; + } + if (w instanceof VOverlay + && "VCalendarPanel".equals(widgetClassName)) { + // Vaadin 7.1 adds a wrapper for datefield popups + parent = (Iterable<?>) ((Iterable<?>) parent).iterator() + .next(); + } + /* + * The new grid and ordered layouts do not contain + * ChildComponentContainer widgets. This is instead simulated by + * constructing a path step that would find the desired widget + * from the layout and injecting it as the next search step + * (which would originally have found the widget inside the + * ChildComponentContainer) + */ + if ((w instanceof VGridLayout) + && "ChildComponentContainer".equals(widgetClassName) + && i + 1 < parts.length) { + + HasWidgets layout = (HasWidgets) w; + + String nextPart = parts[i + 1]; + String[] nextSplit = nextPart.split("\\[", 2); + String nextWidgetClassName = nextSplit[0]; + + // Find the n:th child and count the number of children with + // the same type before it + int nextIndex = 0; + for (Widget child : layout) { + boolean matchingType = nextWidgetClassName.equals(Util + .getSimpleName(child)); + if (matchingType && widgetPosition == 0) { + // This is the n:th child that we looked for + break; + } else if (widgetPosition < 0) { + // Error if we're past the desired position without + // a match + return null; + } else if (matchingType) { + // If this was another child of the expected type, + // increase the count for the next step + nextIndex++; + } + + // Don't count captions + if (!(child instanceof VCaption)) { + widgetPosition--; + } + } + + // Advance to the next step, this time checking for the + // actual child widget + parts[i + 1] = nextWidgetClassName + '[' + nextIndex + ']'; + continue; + } + + // Locate the child + Iterator<? extends Widget> iterator; + + /* + * VWindow and VContextMenu workarounds for backwards + * compatibility + */ + if (widgetClassName.equals("VWindow")) { + List<WindowConnector> windows = client.getUIConnector() + .getSubWindows(); + List<VWindow> windowWidgets = new ArrayList<VWindow>( + windows.size()); + for (WindowConnector wc : windows) { + windowWidgets.add(wc.getWidget()); + } + iterator = windowWidgets.iterator(); + } else if (widgetClassName.equals("VContextMenu")) { + return client.getContextMenu(); + } else { + iterator = (Iterator<? extends Widget>) parent.iterator(); + } + + boolean ok = false; + + // Find the widgetPosition:th child of type "widgetClassName" + while (iterator.hasNext()) { + + Widget child = iterator.next(); + String simpleName2 = Util.getSimpleName(child); + + if (!widgetClassName.equals(simpleName2) + && child instanceof Slot) { + /* + * Support legacy tests without any selector for the + * Slot widget (i.e. /VVerticalLayout[0]/VButton[0]) by + * directly checking the stuff inside the slot + */ + child = ((Slot) child).getWidget(); + simpleName2 = Util.getSimpleName(child); + } + + if (widgetClassName.equals(simpleName2)) { + if (widgetPosition == 0) { + w = child; + ok = true; + break; + } + widgetPosition--; + + } + } + + if (!ok) { + // Did not find the child + return null; + } + } else { + // W identifies something that is not a "HasWidgets". This + // should not happen as all widget containers should implement + // HasWidgets. + return null; + } + } + + return w; + } + + private ServerConnector findConnectorById(ServerConnector root, String id) { + SharedState state = root.getState(); + if (state instanceof AbstractComponentState + && id.equals(((AbstractComponentState) state).id)) { + return root; + } + for (ServerConnector child : root.getChildren()) { + ServerConnector found = findConnectorById(child, id); + if (found != null) { + return found; + } + } + + return null; + } + +} diff --git a/client/src/com/vaadin/client/componentlocator/LocatorStrategy.java b/client/src/com/vaadin/client/componentlocator/LocatorStrategy.java new file mode 100644 index 0000000000..e892f43d76 --- /dev/null +++ b/client/src/com/vaadin/client/componentlocator/LocatorStrategy.java @@ -0,0 +1,122 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.componentlocator; + +import java.util.List; + +import com.google.gwt.user.client.Element; + +/** + * This interface should be implemented by all locator strategies. A locator + * strategy is responsible for generating and decoding a string that identifies + * an element in the DOM. A strategy can implement its own syntax for the + * locator string, which may be completely different from any other strategy's + * syntax. + * + * @since 7.2 + * @author Vaadin Ltd + */ +public interface LocatorStrategy { + + /** + * Test the given input path for formatting errors. If a given path can not + * be validated, the locator strategy will not be attempted. + * + * @param path + * a locator path expression + * @return true, if the implementing class can process the given path, + * otherwise false + */ + boolean validatePath(String path); + + /** + * Generates a String locator which uniquely identifies the target element. + * The {@link #getElementByPath(String)} method can be used for the inverse + * operation, i.e. locating an element based on the return value from this + * method. + * <p> + * Note that getElementByPath(getPathForElement(element)) == element is not + * always true as #getPathForElement(Element) can return a path to another + * element if the widget determines an action on the other element will give + * the same result as the action on the target element. + * </p> + * + * @param targetElement + * The element to generate a path for. + * @return A String locator that identifies the target element or null if a + * String locator could not be created. + */ + String getPathForElement(Element targetElement); + + /** + * Locates an element using a String locator (path) which identifies a DOM + * element. The {@link #getPathForElement(Element)} method can be used for + * the inverse operation, i.e. generating a string expression for a DOM + * element. + * + * @param path + * The String locator which identifies the target element. + * @return The DOM element identified by {@code path} or null if the element + * could not be located. + */ + Element getElementByPath(String path); + + /** + * Locates an element using a String locator (path) which identifies a DOM + * element. The path starts from the specified root element. + * + * @see #getElementByPath(String) + * + * @param path + * The String locator which identifies the target element. + * @param root + * The element that is at the root of the path. + * @return The DOM element identified by {@code path} or null if the element + * could not be located. + */ + Element getElementByPathStartingAt(String path, Element root); + + /** + * Locates all elements that match a String locator (path) which identifies + * DOM elements. + * + * This functionality is limited in {@link LegacyLocatorStrategy}. + * + * @param path + * The String locator which identifies target elements. + * @return List that contains all matched elements. Empty list if none + * found. + */ + List<Element> getElementsByPath(String path); + + /** + * Locates all elements that match a String locator (path) which identifies + * DOM elements. The path starts from the specified root element. + * + * This functionality is limited in {@link LegacyLocatorStrategy}. + * + * @see #getElementsByPath(String) + * + * @param path + * The String locator which identifies target elements. + * @param root + * The element that is at the root of the path. + * @return List that contains all matched elements. Empty list if none + * found. + */ + + List<Element> getElementsByPathStartingAt(String path, Element root); +} diff --git a/client/src/com/vaadin/client/componentlocator/LocatorUtil.java b/client/src/com/vaadin/client/componentlocator/LocatorUtil.java new file mode 100644 index 0000000000..04624920a9 --- /dev/null +++ b/client/src/com/vaadin/client/componentlocator/LocatorUtil.java @@ -0,0 +1,76 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.componentlocator; + +/** + * Common String manipulator utilities used in VaadinFinderLocatorStrategy and + * SelectorPredicates. + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class LocatorUtil { + + /** + * Find first occurrence of character that's not inside quotes starting from + * specified index. + * + * @param str + * Full string for searching + * @param find + * Character we want to find + * @param startingAt + * Index where we start + * @return Index of character. -1 if character not found + */ + protected static int indexOfIgnoringQuoted(String str, char find, + int startingAt) { + boolean quote = false; + String quoteChars = "'\""; + char currentQuote = '"'; + for (int i = startingAt; i < str.length(); ++i) { + char cur = str.charAt(i); + if (quote) { + if (cur == currentQuote) { + quote = !quote; + } + continue; + } else if (cur == find) { + return i; + } else { + if (quoteChars.indexOf(cur) >= 0) { + currentQuote = cur; + quote = !quote; + } + } + } + return -1; + } + + /** + * Find first occurrence of character that's not inside quotes starting from + * the beginning of string. + * + * @param str + * Full string for searching + * @param find + * Character we want to find + * @return Index of character. -1 if character not found + */ + protected static int indexOfIgnoringQuoted(String str, char find) { + return indexOfIgnoringQuoted(str, find, 0); + } +} diff --git a/client/src/com/vaadin/client/componentlocator/SelectorPredicate.java b/client/src/com/vaadin/client/componentlocator/SelectorPredicate.java new file mode 100644 index 0000000000..32b33005ed --- /dev/null +++ b/client/src/com/vaadin/client/componentlocator/SelectorPredicate.java @@ -0,0 +1,228 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.componentlocator; + +import java.util.ArrayList; +import java.util.List; + +/** + * SelectorPredicates are statements about the state of different components + * that VaadinFinderLocatorStrategy is finding. SelectorPredicates also provide + * useful information of said components to debug window by giving means to + * provide better variable naming. + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class SelectorPredicate { + private String name = ""; + private String value = ""; + private boolean wildcard = false; + private int index = -1; + + public static List<SelectorPredicate> extractPostFilterPredicates( + String path) { + if (path.startsWith("(")) { + return extractPredicates(path.substring(path.lastIndexOf(')'))); + } + return new ArrayList<SelectorPredicate>(); + } + + /** + * Generate a list of predicates from a single predicate string + * + * @param str + * a comma separated string of predicates + * @return a List of Predicate objects + */ + public static List<SelectorPredicate> extractPredicates(String path) { + List<SelectorPredicate> predicates = new ArrayList<SelectorPredicate>(); + + String predicateStr = extractPredicateString(path); + if (null == predicateStr || predicateStr.length() == 0) { + return predicates; + } + + // Extract input strings + List<String> input = readPredicatesFromString(predicateStr); + + // Process each predicate into proper predicate descriptor + for (String s : input) { + SelectorPredicate p = new SelectorPredicate(); + s = s.trim(); + + try { + // If we can parse out the predicate as a pure index argument, + // stop processing here. + p.index = Integer.parseInt(s); + predicates.add(p); + + continue; + } catch (Exception e) { + p.index = -1; + } + + int idx = LocatorUtil.indexOfIgnoringQuoted(s, '='); + if (idx < 0) { + continue; + } + p.name = s.substring(0, idx); + p.value = s.substring(idx + 1); + + if (p.value.equals("?")) { + p.wildcard = true; + p.value = null; + } else { + // Only unquote predicate value once we're sure it's a proper + // value... + + p.value = unquote(p.value); + } + + predicates.add(p); + } + // Move any (and all) index predicates to last place in the list. + for (int i = 0, l = predicates.size(); i < l - 1; ++i) { + if (predicates.get(i).index > -1) { + predicates.add(predicates.remove(i)); + --i; + --l; + } + } + + return predicates; + } + + /** + * Splits the predicate string to list of predicate strings. + * + * @param predicateStr + * Comma separated predicate strings + * @return List of predicate strings + */ + private static List<String> readPredicatesFromString(String predicateStr) { + List<String> predicates = new ArrayList<String>(); + int prevIdx = 0; + int idx = LocatorUtil.indexOfIgnoringQuoted(predicateStr, ',', prevIdx); + + while (idx > -1) { + predicates.add(predicateStr.substring(prevIdx, idx)); + prevIdx = idx + 1; + idx = LocatorUtil.indexOfIgnoringQuoted(predicateStr, ',', prevIdx); + } + predicates.add(predicateStr.substring(prevIdx)); + + return predicates; + } + + /** + * Returns the predicate string, i.e. the string between the brackets in a + * path fragment. Examples: <code> + * VTextField[0] => 0 + * VTextField[caption='foo'] => caption='foo' + * </code> + * + * @param pathFragment + * The path fragment from which to extract the predicate string. + * @return The predicate string for the path fragment or empty string if not + * found. + */ + private static String extractPredicateString(String pathFragment) { + int ixOpenBracket = LocatorUtil + .indexOfIgnoringQuoted(pathFragment, '['); + if (ixOpenBracket >= 0) { + int ixCloseBracket = LocatorUtil.indexOfIgnoringQuoted( + pathFragment, ']', ixOpenBracket); + return pathFragment.substring(ixOpenBracket + 1, ixCloseBracket); + } + return ""; + } + + /** + * Removes the surrounding quotes from a string if it is quoted. + * + * @param str + * the possibly quoted string + * @return an unquoted version of str + */ + private static String unquote(String str) { + if ((str.startsWith("\"") && str.endsWith("\"")) + || (str.startsWith("'") && str.endsWith("'"))) { + return str.substring(1, str.length() - 1); + } + return str; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name + * the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the value + */ + public String getValue() { + return value; + } + + /** + * @param value + * the value to set + */ + public void setValue(String value) { + this.value = value; + } + + /** + * @return the index + */ + public int getIndex() { + return index; + } + + /** + * @param index + * the index to set + */ + public void setIndex(int index) { + this.index = index; + } + + /** + * @return the wildcard + */ + public boolean isWildcard() { + return wildcard; + } + + /** + * @param wildcard + * the wildcard to set + */ + public void setWildcard(boolean wildcard) { + this.wildcard = wildcard; + } +} diff --git a/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java b/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java new file mode 100644 index 0000000000..49090b66db --- /dev/null +++ b/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java @@ -0,0 +1,748 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.componentlocator; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.RootPanel; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.HasComponentsConnector; +import com.vaadin.client.Util; +import com.vaadin.client.metadata.Property; +import com.vaadin.client.metadata.TypeDataStore; +import com.vaadin.client.ui.AbstractConnector; +import com.vaadin.client.ui.SubPartAware; +import com.vaadin.client.ui.VNotification; + +/** + * The VaadinFinder locator strategy implements an XPath-like syntax for + * locating elements in Vaadin applications. This is used in the new + * VaadinFinder API in TestBench 4. + * + * Examples of the supported syntax: + * <ul> + * <li>Find the third text field in the DOM: {@code //VTextField[2]}</li> + * <li>Find the second button inside the first vertical layout: + * {@code //VVerticalLayout/VButton[1]}</li> + * <li>Find the first column on the third row of the "Accounts" table: + * {@code //VScrollTable[caption="Accounts"]#row[2]/col[0]}</li> + * </ul> + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class VaadinFinderLocatorStrategy implements LocatorStrategy { + + public static final String SUBPART_SEPARATOR = "#"; + + private final ApplicationConnection client; + + /** + * Internal descriptor for connector/element/widget name combinations + */ + private static final class ConnectorPath { + private String name; + private ComponentConnector connector; + } + + public VaadinFinderLocatorStrategy(ApplicationConnection clientConnection) { + client = clientConnection; + } + + /** + * {@inheritDoc} + */ + @Override + public String getPathForElement(Element targetElement) { + if (targetElement == null) { + return ""; + } + + List<ConnectorPath> hierarchy = getConnectorHierarchyForElement(targetElement); + List<String> path = new ArrayList<String>(); + + // Assemble longname path components back-to-forth with useful + // predicates - first try ID, then caption. + for (int i = 0; i < hierarchy.size(); ++i) { + ConnectorPath cp = hierarchy.get(i); + String pathFragment = cp.name; + String identifier = getPropertyValue(cp.connector, "id"); + + if (identifier != null) { + pathFragment += "[id=\"" + identifier + "\"]"; + } else { + identifier = getPropertyValue(cp.connector, "caption"); + if (identifier != null) { + pathFragment += "[caption=\"" + identifier + "\"]"; + } + } + path.add(pathFragment); + } + + if (path.size() == 0) { + // If we didn't find a single element, return null.. + return null; + } + + return getBestSelector(generateQueries(path), targetElement); + } + + /** + * Search different queries for the best one. Use the fact that the lowest + * possible index is with the last selector. Last selector is the full + * search path containing the complete Component hierarchy. + * + * @param selectors + * List of selectors + * @param target + * Target element + * @return Best selector string formatted with a post filter + */ + private String getBestSelector(List<String> selectors, Element target) { + // The last selector gives us smallest list index for target element. + String bestSelector = selectors.get(selectors.size() - 1); + int min = getElementsByPath(bestSelector).indexOf(target); + if (selectors.size() > 1 + && min == getElementsByPath(selectors.get(0)).indexOf(target)) { + // The first selector has same index as last. It's much shorter. + bestSelector = selectors.get(0); + } else if (selectors.size() > 2) { + // See if we get minimum from second last. If not then we already + // have the best one.. Second last one contains almost full + // component hierarchy. + if (getElementsByPath(selectors.get(selectors.size() - 2)).indexOf( + target) == min) { + for (int i = 1; i < selectors.size() - 2; ++i) { + // Loop through the remaining selectors and look for one + // with the same index + if (getElementsByPath(selectors.get(i)).indexOf(target) == min) { + bestSelector = selectors.get(i); + break; + } + } + + } + } + return "(" + bestSelector + ")[" + min + "]"; + + } + + /** + * Function to generate all possible search paths for given component list. + * Function strips out all the com.vaadin.ui. prefixes from elements as this + * functionality makes generating a query later on easier. + * + * @param components + * List of components + * @return List of Vaadin selectors + */ + private List<String> generateQueries(List<String> components) { + // Prepare to loop through all the elements. + List<String> paths = new ArrayList<String>(); + int compIdx = 0; + String basePath = components.get(compIdx).replace("com.vaadin.ui.", ""); + // Add a basic search for the first element (eg. //Button) + paths.add((components.size() == 1 ? "/" : "//") + basePath); + while (++compIdx < components.size()) { + // Loop through the remaining components + for (int i = components.size() - 1; i >= compIdx; --i) { + boolean recursive = false; + if (i > compIdx) { + recursive = true; + } + paths.add((i == components.size() - 1 ? "/" : "//") + + components.get(i).replace("com.vaadin.ui.", "") + + (recursive ? "//" : "/") + basePath); + } + // Add the element at index compIdx to the basePath so it is + // included in all the following searches. + basePath = components.get(compIdx).replace("com.vaadin.ui.", "") + + "/" + basePath; + } + + return paths; + } + + /** + * Helper method to get the string-form value of a named property of a + * component connector + * + * @since 7.2 + * @param c + * any ComponentConnector instance + * @param propertyName + * property name to test for + * @return a string, if the property is found, or null, if the property does + * not exist on the object (or some other error is encountered). + */ + private String getPropertyValue(ComponentConnector c, String propertyName) { + Property prop = AbstractConnector.getStateType(c).getProperty( + propertyName); + try { + return prop.getValue(c.getState()).toString(); + } catch (Exception e) { + return null; + } + } + + /** + * Generate a list representing the top-to-bottom connector hierarchy for + * any given element. ConnectorPath element provides long- and short names, + * as well as connector and widget root element references. + * + * @since 7.2 + * @param elem + * any Element that is part of a widget hierarchy + * @return a list of ConnectorPath objects, in descending order towards the + * common root container. + */ + private List<ConnectorPath> getConnectorHierarchyForElement(Element elem) { + Element e = elem; + ComponentConnector c = Util.findPaintable(client, e); + List<ConnectorPath> connectorHierarchy = new ArrayList<ConnectorPath>(); + + while (c != null) { + + for (String id : getIDsForConnector(c)) { + ConnectorPath cp = new ConnectorPath(); + cp.name = getFullClassName(id); + cp.connector = c; + + // We want to make an exception for the UI object, since it's + // our default search context (and can't be found inside itself) + if (!cp.name.equals("com.vaadin.ui.UI")) { + connectorHierarchy.add(cp); + } + } + + e = (Element) e.getParentElement(); + if (e != null) { + c = Util.findPaintable(client, e); + e = c != null ? c.getWidget().getElement() : null; + } + + } + + return connectorHierarchy; + } + + private boolean isNotificationExpression(String path) { + String[] starts = { "//", "/" }; + + String[] frags = { "com.vaadin.ui.Notification.class", + "com.vaadin.ui.Notification", "VNotification.class", + "VNotification", "Notification.class", "Notification" }; + + String[] ends = { "/", "[" }; + + for (String s : starts) { + for (String f : frags) { + if (path.equals(s + f)) { + return true; + } + + for (String e : ends) { + if (path.startsWith(s + f + e)) { + return true; + } + } + } + } + + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public List<Element> getElementsByPath(String path) { + List<SelectorPredicate> postFilters = SelectorPredicate + .extractPostFilterPredicates(path); + if (postFilters.size() > 0) { + path = path.substring(1, path.lastIndexOf(')')); + } + + List<Element> elements = new ArrayList<Element>(); + if (isNotificationExpression(path)) { + + for (VNotification n : findNotificationsByPath(path)) { + elements.add(n.getElement()); + } + + } else { + + elements.addAll(eliminateDuplicates(getElementsByPathStartingAtConnector( + path, client.getUIConnector()))); + } + + for (SelectorPredicate p : postFilters) { + // Post filtering supports only indexes and follows instruction + // blindly. Index that is outside of our list results into an empty + // list and multiple indexes are likely to ruin a search completely + if (p.getIndex() >= 0) { + if (p.getIndex() >= elements.size()) { + elements.clear(); + } else { + Element e = elements.get(p.getIndex()); + elements.clear(); + elements.add(e); + } + } + } + + return elements; + } + + /** + * {@inheritDoc} + */ + @Override + public Element getElementByPath(String path) { + List<Element> elements = getElementsByPath(path); + if (elements.isEmpty()) { + return null; + } + return elements.get(0); + } + + /** + * {@inheritDoc} + */ + @Override + public Element getElementByPathStartingAt(String path, Element root) { + List<Element> elements = getElementsByPathStartingAt(path, root); + if (elements.isEmpty()) { + return null; + } + return elements.get(0); + + } + + /** + * {@inheritDoc} + */ + @Override + public List<Element> getElementsByPathStartingAt(String path, Element root) { + List<SelectorPredicate> postFilters = SelectorPredicate + .extractPostFilterPredicates(path); + if (postFilters.size() > 0) { + path = path.substring(1, path.lastIndexOf(')')); + } + + List<Element> elements = getElementsByPathStartingAtConnector(path, + Util.findPaintable(client, root)); + + for (SelectorPredicate p : postFilters) { + // Post filtering supports only indexes and follows instruction + // blindly. Index that is outside of our list results into an empty + // list and multiple indexes are likely to ruin a search completely + if (p.getIndex() >= 0) { + if (p.getIndex() >= elements.size()) { + elements.clear(); + } else { + Element e = elements.get(p.getIndex()); + elements.clear(); + elements.add(e); + } + } + } + + return elements; + } + + /** + * Special case for finding notifications as they have no connectors and are + * directly attached to {@link RootPanel}. + * + * @param path + * The path of the notification, should be + * {@code "//VNotification"} optionally followed by an index in + * brackets. + * @return the notification element or null if not found. + */ + private List<VNotification> findNotificationsByPath(String path) { + + List<VNotification> notifications = new ArrayList<VNotification>(); + for (Widget w : RootPanel.get()) { + if (w instanceof VNotification) { + notifications.add((VNotification) w); + } + } + + List<SelectorPredicate> predicates = SelectorPredicate + .extractPredicates(path); + for (SelectorPredicate p : predicates) { + + if (p.getIndex() > -1) { + VNotification n = notifications.get(p.getIndex()); + notifications.clear(); + if (n != null) { + notifications.add(n); + } + } + + } + + return eliminateDuplicates(notifications); + } + + /** + * Finds a list of elements by the specified path, starting traversal of the + * connector hierarchy from the specified root. + * + * @param path + * the locator path + * @param root + * the root connector + * @return the list of elements identified by path or empty list if not + * found. + */ + private List<Element> getElementsByPathStartingAtConnector(String path, + ComponentConnector root) { + String[] pathComponents = path.split(SUBPART_SEPARATOR); + List<ComponentConnector> connectors; + if (pathComponents[0].length() > 0) { + connectors = findConnectorsByPath(pathComponents[0], + Arrays.asList(root)); + } else { + connectors = Arrays.asList(root); + } + + List<Element> output = new ArrayList<Element>(); + if (null != connectors && !connectors.isEmpty()) { + if (pathComponents.length > 1) { + // We have subparts + for (ComponentConnector connector : connectors) { + if (connector.getWidget() instanceof SubPartAware) { + output.add(((SubPartAware) connector.getWidget()) + .getSubPartElement(pathComponents[1])); + } + } + } else { + for (ComponentConnector connector : connectors) { + output.add(connector.getWidget().getElement()); + } + } + } + return eliminateDuplicates(output); + } + + /** + * Recursively finds connectors for the elements identified by the provided + * path by traversing the connector hierarchy starting from {@code parents} + * connectors. + * + * @param path + * The path identifying elements. + * @param parents + * The list of connectors to start traversing from. + * @return The list of connectors identified by {@code path} or empty list + * if no such connectors could be found. + */ + private List<ComponentConnector> findConnectorsByPath(String path, + List<ComponentConnector> parents) { + boolean findRecursively = path.startsWith("//"); + // Strip away the one or two slashes from the beginning of the path + path = path.substring(findRecursively ? 2 : 1); + + String[] fragments = splitFirstFragmentFromTheRest(path); + + List<ComponentConnector> connectors = new ArrayList<ComponentConnector>(); + for (ComponentConnector parent : parents) { + connectors.addAll(filterMatches( + collectPotentialMatches(parent, fragments[0], + findRecursively), SelectorPredicate + .extractPredicates(fragments[0]))); + } + + if (!connectors.isEmpty() && fragments.length > 1) { + return (findConnectorsByPath(fragments[1], connectors)); + } + return eliminateDuplicates(connectors); + } + + /** + * Go through a list of potentially matching components, modifying that list + * until all elements that remain in that list match the complete list of + * predicates. + * + * @param potentialMatches + * a list of component connectors. Will be changed. + * @param predicates + * an immutable list of predicates + * @return filtered list of component connectors. + */ + private List<ComponentConnector> filterMatches( + List<ComponentConnector> potentialMatches, + List<SelectorPredicate> predicates) { + + for (SelectorPredicate p : predicates) { + + if (p.getIndex() > -1) { + try { + ComponentConnector v = potentialMatches.get(p.getIndex()); + potentialMatches.clear(); + potentialMatches.add(v); + } catch (IndexOutOfBoundsException e) { + potentialMatches.clear(); + } + + continue; + } + + for (int i = 0, l = potentialMatches.size(); i < l; ++i) { + + String propData = getPropertyValue(potentialMatches.get(i), + p.getName()); + + if ((p.isWildcard() && propData == null) + || (!p.isWildcard() && !p.getValue().equals(propData))) { + potentialMatches.remove(i); + --l; + --i; + } + } + + } + + return eliminateDuplicates(potentialMatches); + } + + /** + * Collects all connectors that match the widget class name of the path + * fragment. If the {@code collectRecursively} parameter is true, a + * depth-first search of the connector hierarchy is performed. + * + * Searching depth-first ensure that we can return the matches in correct + * order for selecting based on index predicates. + * + * @param parent + * The {@link ComponentConnector} to start the search from. + * @param pathFragment + * The path fragment identifying which type of widget to search + * for. + * @param collectRecursively + * If true, all matches from all levels below {@code parent} will + * be collected. If false only direct children will be collected. + * @return A list of {@link ComponentConnector}s matching the widget type + * specified in the {@code pathFragment}. + */ + private List<ComponentConnector> collectPotentialMatches( + ComponentConnector parent, String pathFragment, + boolean collectRecursively) { + ArrayList<ComponentConnector> potentialMatches = new ArrayList<ComponentConnector>(); + if (parent instanceof HasComponentsConnector) { + List<ComponentConnector> children = ((HasComponentsConnector) parent) + .getChildComponents(); + for (ComponentConnector child : children) { + String widgetName = getWidgetName(pathFragment); + if (connectorMatchesPathFragment(child, widgetName)) { + potentialMatches.add(child); + } + if (collectRecursively) { + potentialMatches.addAll(collectPotentialMatches(child, + pathFragment, collectRecursively)); + } + } + } + return eliminateDuplicates(potentialMatches); + } + + private List<String> getIDsForConnector(ComponentConnector connector) { + Class<?> connectorClass = connector.getClass(); + List<String> ids = new ArrayList<String>(); + + TypeDataStore.get().findIdentifiersFor(connectorClass).addAllTo(ids); + + return ids; + } + + /** + * Determines whether a connector matches a path fragment. This is done by + * comparing the path fragment to the name of the widget type of the + * connector. + * + * @param connector + * The connector to compare. + * @param widgetName + * The name of the widget class. + * @return true if the widget type of the connector equals the widget type + * identified by the path fragment. + */ + private boolean connectorMatchesPathFragment(ComponentConnector connector, + String widgetName) { + + List<String> ids = getIDsForConnector(connector); + + Integer[] widgetTags = client.getConfiguration() + .getTagsForServerSideClassName(getFullClassName(widgetName)); + if (widgetTags.length == 0) { + widgetTags = client.getConfiguration() + .getTagsForServerSideClassName( + getFullClassName("com.vaadin.ui." + widgetName)); + } + + for (int i = 0, l = ids.size(); i < l; ++i) { + + // Fuzz the connector name, so that the client can provide (for + // example: /Button, /Button.class, /com.vaadin.ui.Button, + // /com.vaadin.ui.Button.class, etc) + + String name = ids.get(i); + final String simpleName = getSimpleClassName(name); + final String fullName = getFullClassName(name); + + if (widgetTags.length > 0) { + Integer[] foundTags = client.getConfiguration() + .getTagsForServerSideClassName(fullName); + for (int tag : foundTags) { + if (tagsMatch(widgetTags, tag)) { + return true; + } + } + } + + // Fallback if something failed before. + if (widgetName.equals(fullName + ".class") + || widgetName.equals(fullName) + || widgetName.equals(simpleName + ".class") + || widgetName.equals(simpleName) || widgetName.equals(name)) { + return true; + } + } + + // If the server-side class name didn't match, fall back to testing for + // the explicit widget name + String widget = Util.getSimpleName(connector.getWidget()); + return widgetName.equals(widget) + || widgetName.equals(widget + ".class"); + + } + + /** + * Extracts the name of the widget class from a path fragment + * + * @param pathFragment + * the path fragment + * @return the name of the widget class. + */ + private String getWidgetName(String pathFragment) { + String widgetName = pathFragment; + int ixBracket = pathFragment.indexOf('['); + if (ixBracket >= 0) { + widgetName = pathFragment.substring(0, ixBracket); + } + return widgetName; + } + + /** + * Splits off the first path fragment from a path and returns an array of + * two elements, where the first element is the first path fragment and the + * second element is the rest of the path (all remaining path fragments + * untouched). + * + * @param path + * The path to split. + * @return An array of two elements: The first path fragment and the rest of + * the path. + */ + private String[] splitFirstFragmentFromTheRest(String path) { + int ixOfSlash = LocatorUtil.indexOfIgnoringQuoted(path, '/'); + if (ixOfSlash > 0) { + return new String[] { path.substring(0, ixOfSlash), + path.substring(ixOfSlash) }; + } + return new String[] { path }; + } + + private String getSimpleClassName(String s) { + String[] parts = s.split("\\."); + if (s.endsWith(".class")) { + return parts[parts.length - 2]; + } + return parts.length > 0 ? parts[parts.length - 1] : s; + } + + private String getFullClassName(String s) { + if (s.endsWith(".class")) { + return s.substring(0, s.lastIndexOf(".class")); + } + return s; + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.client.componentlocator.LocatorStrategy#validatePath(java. + * lang.String) + */ + @Override + public boolean validatePath(String path) { + // This syntax is so difficult to regexp properly, that we'll just try + // to find something with it regardless of the correctness of the + // syntax... + return true; + } + + /** + * Go through a list, removing all duplicate elements from it. This method + * is used to avoid accumulation of duplicate entries in result lists + * resulting from low-context recursion. + * + * Preserves first entry in list, removes others. Preserves list order. + * + * @return list passed as parameter, after modification + */ + private final <T> List<T> eliminateDuplicates(List<T> list) { + + int l = list.size(); + for (int j = 0; j < l; ++j) { + T ref = list.get(j); + + for (int i = j + 1; i < l; ++i) { + if (list.get(i) == ref) { + list.remove(i); + --i; + --l; + } + } + } + + return list; + } + + private boolean tagsMatch(Integer[] targets, Integer tag) { + for (int i = 0; i < targets.length; ++i) { + if (targets[i].equals(tag)) { + return true; + } + } + + try { + return tagsMatch(targets, + client.getConfiguration().getParentTag(tag)); + } catch (Exception e) { + return false; + } + } +} diff --git a/client/src/com/vaadin/client/debug/internal/AnalyzeLayoutsPanel.java b/client/src/com/vaadin/client/debug/internal/AnalyzeLayoutsPanel.java new file mode 100644 index 0000000000..7561bc2c03 --- /dev/null +++ b/client/src/com/vaadin/client/debug/internal/AnalyzeLayoutsPanel.java @@ -0,0 +1,267 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.debug.internal; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.google.gwt.core.client.JsArray; +import com.google.gwt.dom.client.Style.TextDecoration; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.MouseOutEvent; +import com.google.gwt.event.dom.client.MouseOutHandler; +import com.google.gwt.event.dom.client.MouseOverEvent; +import com.google.gwt.event.dom.client.MouseOverHandler; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ApplicationConfiguration; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ComputedStyle; +import com.vaadin.client.ConnectorMap; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.SimpleTree; +import com.vaadin.client.Util; +import com.vaadin.client.ValueMap; + +/** + * Analyze layouts view panel of the debug window. + * + * @since 7.1.4 + */ +public class AnalyzeLayoutsPanel extends FlowPanel { + + private List<SelectConnectorListener> listeners = new ArrayList<SelectConnectorListener>(); + + public void update() { + clear(); + add(new Label("Analyzing layouts...")); + List<ApplicationConnection> runningApplications = ApplicationConfiguration + .getRunningApplications(); + for (ApplicationConnection applicationConnection : runningApplications) { + applicationConnection.analyzeLayouts(); + } + } + + public void meta(ApplicationConnection ac, ValueMap meta) { + clear(); + JsArray<ValueMap> valueMapArray = meta + .getJSValueMapArray("invalidLayouts"); + int size = valueMapArray.length(); + + if (size > 0) { + SimpleTree root = new SimpleTree("Layouts analyzed, " + size + + " top level problems"); + for (int i = 0; i < size; i++) { + printLayoutError(ac, valueMapArray.get(i), root); + } + root.open(false); + add(root); + } else { + add(new Label("Layouts analyzed, no top level problems")); + } + + Set<ComponentConnector> zeroHeightComponents = new HashSet<ComponentConnector>(); + Set<ComponentConnector> zeroWidthComponents = new HashSet<ComponentConnector>(); + findZeroSizeComponents(zeroHeightComponents, zeroWidthComponents, + ac.getUIConnector()); + if (zeroHeightComponents.size() > 0 || zeroWidthComponents.size() > 0) { + add(new HTML("<h4> Client side notifications</h4>" + + " <em>The following relative sized components were " + + "rendered to a zero size container on the client side." + + " Note that these are not necessarily invalid " + + "states, but reported here as they might be.</em>")); + if (zeroHeightComponents.size() > 0) { + add(new HTML("<p><strong>Vertically zero size:</strong></p>")); + printClientSideDetectedIssues(zeroHeightComponents, ac); + } + if (zeroWidthComponents.size() > 0) { + add(new HTML("<p><strong>Horizontally zero size:</strong></p>")); + printClientSideDetectedIssues(zeroWidthComponents, ac); + } + } + + } + + private void printClientSideDetectedIssues( + Set<ComponentConnector> zeroSized, ApplicationConnection ac) { + + // keep track of already highlighted parents + HashSet<String> parents = new HashSet<String>(); + + for (final ComponentConnector connector : zeroSized) { + final ServerConnector parent = connector.getParent(); + final String parentId = parent.getConnectorId(); + + final Label errorDetails = new Label(Util.getSimpleName(connector) + + "[" + connector.getConnectorId() + "]" + " inside " + + Util.getSimpleName(parent)); + + if (parent instanceof ComponentConnector) { + final ComponentConnector parentConnector = (ComponentConnector) parent; + if (!parents.contains(parentId)) { + parents.add(parentId); + Highlight.show(parentConnector, "yellow"); + } + + errorDetails.addMouseOverHandler(new MouseOverHandler() { + @Override + public void onMouseOver(MouseOverEvent event) { + Highlight.hideAll(); + Highlight.show(parentConnector, "yellow"); + Highlight.show(connector); + errorDetails.getElement().getStyle() + .setTextDecoration(TextDecoration.UNDERLINE); + } + }); + errorDetails.addMouseOutHandler(new MouseOutHandler() { + @Override + public void onMouseOut(MouseOutEvent event) { + Highlight.hideAll(); + errorDetails.getElement().getStyle() + .setTextDecoration(TextDecoration.NONE); + } + }); + errorDetails.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + fireSelectEvent(connector); + } + }); + + } + + Highlight.show(connector); + add(errorDetails); + + } + } + + private void printLayoutError(ApplicationConnection ac, ValueMap valueMap, + SimpleTree root) { + final String pid = valueMap.getString("id"); + + // find connector + final ComponentConnector connector = (ComponentConnector) ConnectorMap + .get(ac).getConnector(pid); + + if (connector == null) { + root.add(new SimpleTree("[" + pid + "] NOT FOUND")); + return; + } + + Highlight.show(connector); + + final SimpleTree errorNode = new SimpleTree( + Util.getSimpleName(connector) + " id: " + pid); + errorNode.addDomHandler(new MouseOverHandler() { + @Override + public void onMouseOver(MouseOverEvent event) { + Highlight.showOnly(connector); + ((Widget) event.getSource()).getElement().getStyle() + .setTextDecoration(TextDecoration.UNDERLINE); + } + }, MouseOverEvent.getType()); + errorNode.addDomHandler(new MouseOutHandler() { + @Override + public void onMouseOut(MouseOutEvent event) { + Highlight.hideAll(); + ((Widget) event.getSource()).getElement().getStyle() + .setTextDecoration(TextDecoration.NONE); + } + }, MouseOutEvent.getType()); + + errorNode.addDomHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + if (event.getNativeEvent().getEventTarget().cast() == errorNode + .getElement().getChild(1).cast()) { + fireSelectEvent(connector); + } + } + }, ClickEvent.getType()); + + VerticalPanel errorDetails = new VerticalPanel(); + + if (valueMap.containsKey("heightMsg")) { + errorDetails.add(new Label("Height problem: " + + valueMap.getString("heightMsg"))); + } + if (valueMap.containsKey("widthMsg")) { + errorDetails.add(new Label("Width problem: " + + valueMap.getString("widthMsg"))); + } + if (errorDetails.getWidgetCount() > 0) { + errorNode.add(errorDetails); + } + if (valueMap.containsKey("subErrors")) { + HTML l = new HTML( + "<em>Expand this node to show problems that may be dependent on this problem.</em>"); + errorDetails.add(l); + JsArray<ValueMap> suberrors = valueMap + .getJSValueMapArray("subErrors"); + for (int i = 0; i < suberrors.length(); i++) { + ValueMap value = suberrors.get(i); + printLayoutError(ac, value, errorNode); + } + + } + root.add(errorNode); + } + + private void findZeroSizeComponents( + Set<ComponentConnector> zeroHeightComponents, + Set<ComponentConnector> zeroWidthComponents, + ComponentConnector connector) { + Widget widget = connector.getWidget(); + ComputedStyle computedStyle = new ComputedStyle(widget.getElement()); + if (computedStyle.getIntProperty("height") == 0) { + zeroHeightComponents.add(connector); + } + if (computedStyle.getIntProperty("width") == 0) { + zeroWidthComponents.add(connector); + } + List<ServerConnector> children = connector.getChildren(); + for (ServerConnector serverConnector : children) { + if (serverConnector instanceof ComponentConnector) { + findZeroSizeComponents(zeroHeightComponents, + zeroWidthComponents, + (ComponentConnector) serverConnector); + } + } + } + + public void addListener(SelectConnectorListener listener) { + listeners.add(listener); + } + + public void removeListener(SelectConnectorListener listener) { + listeners.remove(listener); + } + + private void fireSelectEvent(ServerConnector connector) { + for (SelectConnectorListener listener : listeners) { + listener.select(connector, null); + } + } + +} diff --git a/client/src/com/vaadin/client/debug/internal/ConnectorInfoPanel.java b/client/src/com/vaadin/client/debug/internal/ConnectorInfoPanel.java new file mode 100644 index 0000000000..fc7b55497e --- /dev/null +++ b/client/src/com/vaadin/client/debug/internal/ConnectorInfoPanel.java @@ -0,0 +1,107 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.debug.internal; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HTML; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.JsArrayObject; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.Util; +import com.vaadin.client.VConsole; +import com.vaadin.client.metadata.NoDataException; +import com.vaadin.client.metadata.Property; +import com.vaadin.client.ui.AbstractConnector; +import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.communication.SharedState; + +/** + * Connector information view panel of the debug window. + * + * @since 7.1.4 + */ +public class ConnectorInfoPanel extends FlowPanel { + + /** + * Update the panel to show information about a connector. + * + * @param connector + */ + public void update(ServerConnector connector) { + SharedState state = connector.getState(); + + Set<String> ignoreProperties = new HashSet<String>(); + ignoreProperties.add("id"); + + String html = getRowHTML("Id", connector.getConnectorId()); + html += getRowHTML("Connector", Util.getSimpleName(connector)); + + if (connector instanceof ComponentConnector) { + ComponentConnector component = (ComponentConnector) connector; + + ignoreProperties.addAll(Arrays.asList("caption", "description", + "width", "height")); + + AbstractComponentState componentState = component.getState(); + + html += getRowHTML("Widget", + Util.getSimpleName(component.getWidget())); + html += getRowHTML("Caption", componentState.caption); + html += getRowHTML("Description", componentState.description); + html += getRowHTML("Width", componentState.width + " (actual: " + + component.getWidget().getOffsetWidth() + "px)"); + html += getRowHTML("Height", componentState.height + " (actual: " + + component.getWidget().getOffsetHeight() + "px)"); + } + + try { + JsArrayObject<Property> properties = AbstractConnector + .getStateType(connector).getPropertiesAsArray(); + for (int i = 0; i < properties.size(); i++) { + Property property = properties.get(i); + String name = property.getName(); + if (!ignoreProperties.contains(name)) { + html += getRowHTML(property.getDisplayName(), + property.getValue(state)); + } + } + } catch (NoDataException e) { + html += "<div>Could not read state, error has been logged to the console</div>"; + VConsole.error(e); + } + + clear(); + add(new HTML(html)); + } + + private String getRowHTML(String caption, Object value) { + return "<div class=\"" + VDebugWindow.STYLENAME + + "-row\"><span class=\"caption\">" + caption + + "</span><span class=\"value\">" + + Util.escapeHTML(String.valueOf(value)) + "</span></div>"; + } + + /** + * Clear the contents of the panel. + */ + public void clearContents() { + clear(); + } +} diff --git a/client/src/com/vaadin/client/debug/internal/HierarchyPanel.java b/client/src/com/vaadin/client/debug/internal/HierarchyPanel.java new file mode 100644 index 0000000000..755f076b7a --- /dev/null +++ b/client/src/com/vaadin/client/debug/internal/HierarchyPanel.java @@ -0,0 +1,178 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.debug.internal; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.DoubleClickEvent; +import com.google.gwt.event.dom.client.DoubleClickHandler; +import com.google.gwt.event.dom.client.HasDoubleClickHandlers; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HasWidgets; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ApplicationConfiguration; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.FastStringSet; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.SimpleTree; +import com.vaadin.client.Util; + +/** + * Hierarchy view panel of the debug window. This class can be used in various + * debug window sections to show the current connector hierarchy. + * + * @since 7.1.4 + */ +public class HierarchyPanel extends FlowPanel { + + // TODO separate click listeners for simple selection and doubleclick + private List<SelectConnectorListener> listeners = new ArrayList<SelectConnectorListener>(); + + public void update() { + // Try to keep track of currently open nodes and reopen them + FastStringSet openNodes = FastStringSet.create(); + Iterator<Widget> it = iterator(); + while (it.hasNext()) { + collectOpenNodes(it.next(), openNodes); + } + + clear(); + + SimplePanel trees = new SimplePanel(); + + for (ApplicationConnection application : ApplicationConfiguration + .getRunningApplications()) { + ServerConnector uiConnector = application.getUIConnector(); + Widget connectorTree = buildConnectorTree(uiConnector, openNodes); + + trees.add(connectorTree); + } + + add(trees); + } + + /** + * Adds the captions of all open (non-leaf) nodes in the hierarchy tree + * recursively. + * + * @param widget + * the widget in which to search for open nodes (if SimpleTree) + * @param openNodes + * the set in which open nodes should be added + */ + private void collectOpenNodes(Widget widget, FastStringSet openNodes) { + if (widget instanceof SimpleTree) { + SimpleTree tree = (SimpleTree) widget; + if (tree.isOpen()) { + openNodes.add(tree.getCaption()); + } else { + // no need to look inside closed nodes + return; + } + } + if (widget instanceof HasWidgets) { + Iterator<Widget> it = ((HasWidgets) widget).iterator(); + while (it.hasNext()) { + collectOpenNodes(it.next(), openNodes); + } + } + } + + private Widget buildConnectorTree(final ServerConnector connector, + FastStringSet openNodes) { + String connectorString = Util.getConnectorString(connector); + + List<ServerConnector> children = connector.getChildren(); + + Widget widget; + if (children == null || children.isEmpty()) { + // Leaf node, just add a label + Label label = new Label(connectorString); + label.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + Highlight.showOnly(connector); + showServerDebugInfo(connector); + } + }); + widget = label; + } else { + SimpleTree tree = new SimpleTree(connectorString) { + @Override + protected void select(ClickEvent event) { + super.select(event); + Highlight.showOnly(connector); + showServerDebugInfo(connector); + } + }; + for (ServerConnector child : children) { + tree.add(buildConnectorTree(child, openNodes)); + } + if (openNodes.contains(connectorString)) { + tree.open(false); + } + widget = tree; + } + + if (widget instanceof HasDoubleClickHandlers) { + HasDoubleClickHandlers has = (HasDoubleClickHandlers) widget; + has.addDoubleClickHandler(new DoubleClickHandler() { + @Override + public void onDoubleClick(DoubleClickEvent event) { + fireSelectEvent(connector); + } + }); + } + + return widget; + } + + public void addListener(SelectConnectorListener listener) { + listeners.add(listener); + } + + public void removeListener(SelectConnectorListener listener) { + listeners.remove(listener); + } + + private void fireSelectEvent(ServerConnector connector) { + for (SelectConnectorListener listener : listeners) { + listener.select(connector, null); + } + } + + /** + * Outputs debug information on the server - usually in the console of an + * IDE, with a clickable reference to the relevant code location. + * + * @since 7.1 + * @param connector + * show debug info for this connector + */ + static void showServerDebugInfo(ServerConnector connector) { + if (connector != null) { + connector.getConnection().getUIConnector() + .showServerDebugInfo(connector); + } + } + +} diff --git a/client/src/com/vaadin/client/debug/internal/HierarchySection.java b/client/src/com/vaadin/client/debug/internal/HierarchySection.java index 90c9086d7d..616bf70c38 100644 --- a/client/src/com/vaadin/client/debug/internal/HierarchySection.java +++ b/client/src/com/vaadin/client/debug/internal/HierarchySection.java @@ -15,23 +15,9 @@ */ package com.vaadin.client.debug.internal; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.google.gwt.core.client.JsArray; -import com.google.gwt.dom.client.Style.TextDecoration; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.DoubleClickEvent; -import com.google.gwt.event.dom.client.DoubleClickHandler; -import com.google.gwt.event.dom.client.HasDoubleClickHandlers; import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.MouseOutEvent; -import com.google.gwt.event.dom.client.MouseOutHandler; -import com.google.gwt.event.dom.client.MouseOverEvent; -import com.google.gwt.event.dom.client.MouseOverHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; @@ -40,28 +26,15 @@ import com.google.gwt.user.client.Event.NativePreviewHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConfiguration; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.ComponentConnector; -import com.vaadin.client.ComputedStyle; -import com.vaadin.client.ConnectorMap; -import com.vaadin.client.JsArrayObject; import com.vaadin.client.ServerConnector; -import com.vaadin.client.SimpleTree; import com.vaadin.client.Util; -import com.vaadin.client.VConsole; import com.vaadin.client.ValueMap; -import com.vaadin.client.metadata.NoDataException; -import com.vaadin.client.metadata.Property; -import com.vaadin.client.ui.AbstractConnector; -import com.vaadin.client.ui.UnknownComponentConnector; -import com.vaadin.shared.AbstractComponentState; -import com.vaadin.shared.communication.SharedState; /** * Provides functionality for examining the UI component hierarchy. @@ -73,7 +46,15 @@ public class HierarchySection implements Section { private final DebugButton tabButton = new DebugButton(Icon.HIERARCHY, "Examine component hierarchy"); - private final FlowPanel content = new FlowPanel(); + private final SimplePanel content = new SimplePanel(); + + // TODO highlighting logic is split between these, should be refactored + private final FlowPanel helpPanel = new FlowPanel(); + private final ConnectorInfoPanel infoPanel = new ConnectorInfoPanel(); + private final HierarchyPanel hierarchyPanel = new HierarchyPanel(); + private final OptimizedWidgetsetPanel widgetsetPanel = new OptimizedWidgetsetPanel(); + private final AnalyzeLayoutsPanel analyzeLayoutsPanel = new AnalyzeLayoutsPanel(); + private final FlowPanel controls = new FlowPanel(); private final Button find = new DebugButton(Icon.HIGHLIGHT, @@ -125,79 +106,40 @@ public class HierarchySection implements Section { } }); + hierarchyPanel.addListener(new SelectConnectorListener() { + @Override + public void select(ServerConnector connector, Element element) { + printState(connector, true); + } + }); + + analyzeLayoutsPanel.addListener(new SelectConnectorListener() { + @Override + public void select(ServerConnector connector, Element element) { + printState(connector, true); + } + }); + content.setStylePrimaryName(VDebugWindow.STYLENAME + "-hierarchy"); + initializeHelpPanel(); + content.setWidget(helpPanel); + } + + private void initializeHelpPanel() { HTML info = new HTML(showHierarchy.getHTML() + " " + showHierarchy.getTitle() + "<br/>" + find.getHTML() + " " + find.getTitle() + "<br/>" + analyze.getHTML() + " " + analyze.getTitle() + "<br/>" + generateWS.getHTML() + " " + generateWS.getTitle() + "<br/>"); info.setStyleName(VDebugWindow.STYLENAME + "-info"); - content.add(info); + helpPanel.add(info); } private void showHierarchy() { Highlight.hideAll(); - content.clear(); - - // TODO Clearing and rebuilding the contents is not optimal for UX as - // any previous expansions are lost. - SimplePanel trees = new SimplePanel(); - - for (ApplicationConnection application : ApplicationConfiguration - .getRunningApplications()) { - ServerConnector uiConnector = application.getUIConnector(); - Widget connectorTree = buildConnectorTree(uiConnector); - - trees.add(connectorTree); - } - - content.add(trees); - } - - private Widget buildConnectorTree(final ServerConnector connector) { - String connectorString = Util.getConnectorString(connector); - - List<ServerConnector> children = connector.getChildren(); - - Widget widget; - if (children == null || children.isEmpty()) { - // Leaf node, just add a label - Label label = new Label(connectorString); - label.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - Highlight.showOnly(connector); - Highlight.showServerDebugInfo(connector); - } - }); - widget = label; - } else { - SimpleTree tree = new SimpleTree(connectorString) { - @Override - protected void select(ClickEvent event) { - super.select(event); - Highlight.showOnly(connector); - Highlight.showServerDebugInfo(connector); - } - }; - for (ServerConnector child : children) { - tree.add(buildConnectorTree(child)); - } - widget = tree; - } - - if (widget instanceof HasDoubleClickHandlers) { - HasDoubleClickHandlers has = (HasDoubleClickHandlers) widget; - has.addDoubleClickHandler(new DoubleClickHandler() { - @Override - public void onDoubleClick(DoubleClickEvent event) { - printState(connector, true); - } - }); - } - - return widget; + hierarchyPanel.update(); + content.setWidget(hierarchyPanel); } @Override @@ -226,302 +168,19 @@ public class HierarchySection implements Section { } private void generateWidgetset() { - - content.clear(); - HTML h = new HTML("Getting used connectors"); - content.add(h); - - String s = ""; - for (ApplicationConnection ac : ApplicationConfiguration - .getRunningApplications()) { - ApplicationConfiguration conf = ac.getConfiguration(); - s += "<h1>Used connectors for " + conf.getServiceUrl() + "</h1>"; - - for (String connectorName : getUsedConnectorNames(conf)) { - s += connectorName + "<br/>"; - } - - s += "<h2>To make an optimized widgetset based on these connectors, do:</h2>"; - s += "<h3>1. Add to your widgetset.gwt.xml file:</h2>"; - s += "<textarea rows=\"3\" style=\"width:90%\">"; - s += "<generate-with class=\"OptimizedConnectorBundleLoaderFactory\">\n"; - s += " <when-type-assignable class=\"com.vaadin.client.metadata.ConnectorBundleLoader\" />\n"; - s += "</generate-with>"; - s += "</textarea>"; - - s += "<h3>2. Add the following java file to your project:</h2>"; - s += "<textarea rows=\"5\" style=\"width:90%\">"; - s += generateOptimizedWidgetSet(getUsedConnectorNames(conf)); - s += "</textarea>"; - s += "<h3>3. Recompile widgetset</h2>"; - - } - - h.setHTML(s); - } - - private Set<String> getUsedConnectorNames( - ApplicationConfiguration configuration) { - int tag = 0; - Set<String> usedConnectors = new HashSet<String>(); - while (true) { - String serverSideClass = configuration - .getServerSideClassNameForTag(tag); - if (serverSideClass == null) { - break; - } - Class<? extends ServerConnector> connectorClass = configuration - .getConnectorClassByEncodedTag(tag); - if (connectorClass == null) { - break; - } - - if (connectorClass != UnknownComponentConnector.class) { - usedConnectors.add(connectorClass.getName()); - } - tag++; - if (tag > 10000) { - // Sanity check - VConsole.error("Search for used connector classes was forcefully terminated"); - break; - } - } - return usedConnectors; - } - - public String generateOptimizedWidgetSet(Set<String> usedConnectors) { - String s = "import java.util.HashSet;\n"; - s += "import java.util.Set;\n"; - - s += "import com.google.gwt.core.ext.typeinfo.JClassType;\n"; - s += "import com.vaadin.client.ui.ui.UIConnector;\n"; - s += "import com.vaadin.server.widgetsetutils.ConnectorBundleLoaderFactory;\n"; - s += "import com.vaadin.shared.ui.Connect.LoadStyle;\n\n"; - - s += "public class OptimizedConnectorBundleLoaderFactory extends\n"; - s += " ConnectorBundleLoaderFactory {\n"; - s += " private Set<String> eagerConnectors = new HashSet<String>();\n"; - s += " {\n"; - for (String c : usedConnectors) { - s += " eagerConnectors.add(" + c - + ".class.getName());\n"; - } - s += " }\n"; - s += "\n"; - s += " @Override\n"; - s += " protected LoadStyle getLoadStyle(JClassType connectorType) {\n"; - s += " if (eagerConnectors.contains(connectorType.getQualifiedBinaryName())) {\n"; - s += " return LoadStyle.EAGER;\n"; - s += " } else {\n"; - s += " // Loads all other connectors immediately after the initial view has\n"; - s += " // been rendered\n"; - s += " return LoadStyle.DEFERRED;\n"; - s += " }\n"; - s += " }\n"; - s += "}\n"; - - return s; + widgetsetPanel.update(); + content.setWidget(widgetsetPanel); } private void analyzeLayouts() { - content.clear(); - content.add(new Label("Analyzing layouts...")); - List<ApplicationConnection> runningApplications = ApplicationConfiguration - .getRunningApplications(); - for (ApplicationConnection applicationConnection : runningApplications) { - applicationConnection.analyzeLayouts(); - } + analyzeLayoutsPanel.update(); + content.setWidget(analyzeLayoutsPanel); } @Override public void meta(ApplicationConnection ac, ValueMap meta) { - content.clear(); - JsArray<ValueMap> valueMapArray = meta - .getJSValueMapArray("invalidLayouts"); - int size = valueMapArray.length(); - - if (size > 0) { - SimpleTree root = new SimpleTree("Layouts analyzed, " + size - + " top level problems"); - for (int i = 0; i < size; i++) { - printLayoutError(ac, valueMapArray.get(i), root); - } - root.open(false); - content.add(root); - } else { - content.add(new Label("Layouts analyzed, no top level problems")); - } - - Set<ComponentConnector> zeroHeightComponents = new HashSet<ComponentConnector>(); - Set<ComponentConnector> zeroWidthComponents = new HashSet<ComponentConnector>(); - findZeroSizeComponents(zeroHeightComponents, zeroWidthComponents, - ac.getUIConnector()); - if (zeroHeightComponents.size() > 0 || zeroWidthComponents.size() > 0) { - content.add(new HTML("<h4> Client side notifications</h4>" - + " <em>The following relative sized components were " - + "rendered to a zero size container on the client side." - + " Note that these are not necessarily invalid " - + "states, but reported here as they might be.</em>")); - if (zeroHeightComponents.size() > 0) { - content.add(new HTML( - "<p><strong>Vertically zero size:</strong></p>")); - printClientSideDetectedIssues(zeroHeightComponents, ac); - } - if (zeroWidthComponents.size() > 0) { - content.add(new HTML( - "<p><strong>Horizontally zero size:</strong></p>")); - printClientSideDetectedIssues(zeroWidthComponents, ac); - } - } - - } - - private void printClientSideDetectedIssues( - Set<ComponentConnector> zeroSized, ApplicationConnection ac) { - - // keep track of already highlighted parents - HashSet<String> parents = new HashSet<String>(); - - for (final ComponentConnector connector : zeroSized) { - final ServerConnector parent = connector.getParent(); - final String parentId = parent.getConnectorId(); - - final Label errorDetails = new Label(Util.getSimpleName(connector) - + "[" + connector.getConnectorId() + "]" + " inside " - + Util.getSimpleName(parent)); - - if (parent instanceof ComponentConnector) { - final ComponentConnector parentConnector = (ComponentConnector) parent; - if (!parents.contains(parentId)) { - parents.add(parentId); - Highlight.show(parentConnector, "yellow"); - } - - errorDetails.addMouseOverHandler(new MouseOverHandler() { - @Override - public void onMouseOver(MouseOverEvent event) { - Highlight.hideAll(); - Highlight.show(parentConnector, "yellow"); - Highlight.show(connector); - errorDetails.getElement().getStyle() - .setTextDecoration(TextDecoration.UNDERLINE); - } - }); - errorDetails.addMouseOutHandler(new MouseOutHandler() { - @Override - public void onMouseOut(MouseOutEvent event) { - Highlight.hideAll(); - errorDetails.getElement().getStyle() - .setTextDecoration(TextDecoration.NONE); - } - }); - errorDetails.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - printState(connector, true); - } - }); - - } - - Highlight.show(connector); - content.add(errorDetails); - - } - } - - private void printLayoutError(ApplicationConnection ac, ValueMap valueMap, - SimpleTree root) { - final String pid = valueMap.getString("id"); - - // find connector - final ComponentConnector connector = (ComponentConnector) ConnectorMap - .get(ac).getConnector(pid); - - if (connector == null) { - root.add(new SimpleTree("[" + pid + "] NOT FOUND")); - return; - } - - Highlight.show(connector); - - final SimpleTree errorNode = new SimpleTree( - Util.getSimpleName(connector) + " id: " + pid); - errorNode.addDomHandler(new MouseOverHandler() { - @Override - public void onMouseOver(MouseOverEvent event) { - Highlight.showOnly(connector); - ((Widget) event.getSource()).getElement().getStyle() - .setTextDecoration(TextDecoration.UNDERLINE); - } - }, MouseOverEvent.getType()); - errorNode.addDomHandler(new MouseOutHandler() { - @Override - public void onMouseOut(MouseOutEvent event) { - Highlight.hideAll(); - ((Widget) event.getSource()).getElement().getStyle() - .setTextDecoration(TextDecoration.NONE); - } - }, MouseOutEvent.getType()); - - errorNode.addDomHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - if (event.getNativeEvent().getEventTarget().cast() == errorNode - .getElement().getChild(1).cast()) { - printState(connector, true); - } - } - }, ClickEvent.getType()); - - VerticalPanel errorDetails = new VerticalPanel(); - - if (valueMap.containsKey("heightMsg")) { - errorDetails.add(new Label("Height problem: " - + valueMap.getString("heightMsg"))); - } - if (valueMap.containsKey("widthMsg")) { - errorDetails.add(new Label("Width problem: " - + valueMap.getString("widthMsg"))); - } - if (errorDetails.getWidgetCount() > 0) { - errorNode.add(errorDetails); - } - if (valueMap.containsKey("subErrors")) { - HTML l = new HTML( - "<em>Expand this node to show problems that may be dependent on this problem.</em>"); - errorDetails.add(l); - JsArray<ValueMap> suberrors = valueMap - .getJSValueMapArray("subErrors"); - for (int i = 0; i < suberrors.length(); i++) { - ValueMap value = suberrors.get(i); - printLayoutError(ac, value, errorNode); - } - - } - root.add(errorNode); - } - - private void findZeroSizeComponents( - Set<ComponentConnector> zeroHeightComponents, - Set<ComponentConnector> zeroWidthComponents, - ComponentConnector connector) { - Widget widget = connector.getWidget(); - ComputedStyle computedStyle = new ComputedStyle(widget.getElement()); - if (computedStyle.getIntProperty("height") == 0) { - zeroHeightComponents.add(connector); - } - if (computedStyle.getIntProperty("width") == 0) { - zeroWidthComponents.add(connector); - } - List<ServerConnector> children = connector.getChildren(); - for (ServerConnector serverConnector : children) { - if (serverConnector instanceof ComponentConnector) { - findZeroSizeComponents(zeroHeightComponents, - zeroWidthComponents, - (ComponentConnector) serverConnector); - } - } + // show the results of analyzeLayouts + analyzeLayoutsPanel.meta(ac, meta); } @Override @@ -561,60 +220,11 @@ public class HierarchySection implements Section { private void printState(ServerConnector connector, boolean serverDebug) { Highlight.showOnly(connector); if (serverDebug) { - Highlight.showServerDebugInfo(connector); + HierarchyPanel.showServerDebugInfo(connector); } - SharedState state = connector.getState(); - - Set<String> ignoreProperties = new HashSet<String>(); - ignoreProperties.add("id"); - - String html = getRowHTML("Id", connector.getConnectorId()); - html += getRowHTML("Connector", Util.getSimpleName(connector)); - - if (connector instanceof ComponentConnector) { - ComponentConnector component = (ComponentConnector) connector; - - ignoreProperties.addAll(Arrays.asList("caption", "description", - "width", "height")); - - AbstractComponentState componentState = component.getState(); - - html += getRowHTML("Widget", - Util.getSimpleName(component.getWidget())); - html += getRowHTML("Caption", componentState.caption); - html += getRowHTML("Description", componentState.description); - html += getRowHTML("Width", componentState.width + " (actual: " - + component.getWidget().getOffsetWidth() + "px)"); - html += getRowHTML("Height", componentState.height + " (actual: " - + component.getWidget().getOffsetHeight() + "px)"); - } - - try { - JsArrayObject<Property> properties = AbstractConnector - .getStateType(connector).getPropertiesAsArray(); - for (int i = 0; i < properties.size(); i++) { - Property property = properties.get(i); - String name = property.getName(); - if (!ignoreProperties.contains(name)) { - html += getRowHTML(property.getDisplayName(), - property.getValue(state)); - } - } - } catch (NoDataException e) { - html += "<div>Could not read state, error has been logged to the console</div>"; - VConsole.error(e); - } - - content.clear(); - content.add(new HTML(html)); - } - - private String getRowHTML(String caption, Object value) { - return "<div class=\"" + VDebugWindow.STYLENAME - + "-row\"><span class=\"caption\">" + caption - + "</span><span class=\"value\">" - + Util.escapeHTML(String.valueOf(value)) + "</span></div>"; + infoPanel.update(connector); + content.setWidget(infoPanel); } private final NativePreviewHandler highlightModeHandler = new NativePreviewHandler() { @@ -634,7 +244,7 @@ public class HierarchySection implements Section { .getNativeEvent().getClientX(), event.getNativeEvent() .getClientY()); if (VDebugWindow.get().getElement().isOrHasChild(eventTarget)) { - content.clear(); + infoPanel.clear(); return; } @@ -654,7 +264,7 @@ public class HierarchySection implements Section { return; } } - content.clear(); + infoPanel.clear(); } if (event.getTypeInt() == Event.ONCLICK) { Highlight.hideAll(); diff --git a/client/src/com/vaadin/client/debug/internal/Highlight.java b/client/src/com/vaadin/client/debug/internal/Highlight.java index 3c1af445a9..5ee3a25e2c 100644 --- a/client/src/com/vaadin/client/debug/internal/Highlight.java +++ b/client/src/com/vaadin/client/debug/internal/Highlight.java @@ -144,20 +144,55 @@ public class Highlight { */ static Element show(Widget widget, String color) { if (widget != null) { + show(widget.getElement(), color); + } + return null; + } + + /** + * Highlights the given {@link Element}. + * <p> + * Pass the returned {@link Element} to {@link #hide(Element)} to remove + * this particular highlight. + * </p> + * + * @param element + * Element to highlight + * @return Highlight element + */ + static Element show(Element element) { + return show(element, DEFAULT_COLOR); + } + + /** + * Highlight the given {@link Element} using the given color. + * <p> + * Pass the returned highlight {@link Element} to {@link #hide(Element)} to + * remove this particular highlight. + * </p> + * + * @param element + * Element to highlight + * @param color + * Color of highlight + * @return Highlight element + */ + static Element show(Element element, String color) { + if (element != null) { if (highlights == null) { highlights = new HashSet<Element>(); } Element highlight = DOM.createDiv(); Style style = highlight.getStyle(); - style.setTop(widget.getAbsoluteTop(), Unit.PX); - style.setLeft(widget.getAbsoluteLeft(), Unit.PX); - int width = widget.getOffsetWidth(); + style.setTop(element.getAbsoluteTop(), Unit.PX); + style.setLeft(element.getAbsoluteLeft(), Unit.PX); + int width = element.getOffsetWidth(); if (width < MIN_WIDTH) { width = MIN_WIDTH; } style.setWidth(width, Unit.PX); - int height = widget.getOffsetHeight(); + int height = element.getOffsetHeight(); if (height < MIN_HEIGHT) { height = MIN_HEIGHT; } @@ -207,19 +242,4 @@ public class Highlight { } } - /** - * Outputs debug information on the server - usually in the console of an - * IDE, with a clickable reference to the relevant code location. - * - * @since 7.1 - * @param connector - * show debug info for this connector - */ - static void showServerDebugInfo(ServerConnector connector) { - if (connector != null) { - connector.getConnection().getUIConnector() - .showServerDebugInfo(connector); - } - } - } diff --git a/client/src/com/vaadin/client/debug/internal/Icon.java b/client/src/com/vaadin/client/debug/internal/Icon.java index cc2ef3b348..9ef6d833e2 100644 --- a/client/src/com/vaadin/client/debug/internal/Icon.java +++ b/client/src/com/vaadin/client/debug/internal/Icon.java @@ -32,6 +32,8 @@ public enum Icon { LOG(""), // OPTIMIZE(""), // HIERARCHY(""), // + // TODO create more appropriate icon + SELECTOR("≣"), // MENU(""), // NETWORK(""), // ANALYZE(""), // diff --git a/client/src/com/vaadin/client/debug/internal/OptimizedWidgetsetPanel.java b/client/src/com/vaadin/client/debug/internal/OptimizedWidgetsetPanel.java new file mode 100644 index 0000000000..a8d8aad888 --- /dev/null +++ b/client/src/com/vaadin/client/debug/internal/OptimizedWidgetsetPanel.java @@ -0,0 +1,137 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.debug.internal; + +import java.util.HashSet; +import java.util.Set; + +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HTML; +import com.vaadin.client.ApplicationConfiguration; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.VConsole; +import com.vaadin.client.ui.UnknownComponentConnector; + +/** + * Optimized widgetset view panel of the debug window. + * + * @since 7.1.4 + */ +public class OptimizedWidgetsetPanel extends FlowPanel { + + /** + * Update the panel contents based on the connectors that have been used so + * far on this execution of the application. + */ + public void update() { + clear(); + HTML h = new HTML("Getting used connectors"); + add(h); + + String s = ""; + for (ApplicationConnection ac : ApplicationConfiguration + .getRunningApplications()) { + ApplicationConfiguration conf = ac.getConfiguration(); + s += "<h1>Used connectors for " + conf.getServiceUrl() + "</h1>"; + + for (String connectorName : getUsedConnectorNames(conf)) { + s += connectorName + "<br/>"; + } + + s += "<h2>To make an optimized widgetset based on these connectors, do:</h2>"; + s += "<h3>1. Add to your widgetset.gwt.xml file:</h2>"; + s += "<textarea rows=\"3\" style=\"width:90%\">"; + s += "<generate-with class=\"OptimizedConnectorBundleLoaderFactory\">\n"; + s += " <when-type-assignable class=\"com.vaadin.client.metadata.ConnectorBundleLoader\" />\n"; + s += "</generate-with>"; + s += "</textarea>"; + + s += "<h3>2. Add the following java file to your project:</h2>"; + s += "<textarea rows=\"5\" style=\"width:90%\">"; + s += generateOptimizedWidgetSet(getUsedConnectorNames(conf)); + s += "</textarea>"; + s += "<h3>3. Recompile widgetset</h2>"; + + } + + h.setHTML(s); + } + + private Set<String> getUsedConnectorNames( + ApplicationConfiguration configuration) { + int tag = 0; + Set<String> usedConnectors = new HashSet<String>(); + while (true) { + String serverSideClass = configuration + .getServerSideClassNameForTag(tag); + if (serverSideClass == null) { + break; + } + Class<? extends ServerConnector> connectorClass = configuration + .getConnectorClassByEncodedTag(tag); + if (connectorClass == null) { + break; + } + + if (connectorClass != UnknownComponentConnector.class) { + usedConnectors.add(connectorClass.getName()); + } + tag++; + if (tag > 10000) { + // Sanity check + VConsole.error("Search for used connector classes was forcefully terminated"); + break; + } + } + return usedConnectors; + } + + public String generateOptimizedWidgetSet(Set<String> usedConnectors) { + String s = "import java.util.HashSet;\n"; + s += "import java.util.Set;\n"; + + s += "import com.google.gwt.core.ext.typeinfo.JClassType;\n"; + s += "import com.vaadin.client.ui.ui.UIConnector;\n"; + s += "import com.vaadin.server.widgetsetutils.ConnectorBundleLoaderFactory;\n"; + s += "import com.vaadin.shared.ui.Connect.LoadStyle;\n\n"; + + s += "public class OptimizedConnectorBundleLoaderFactory extends\n"; + s += " ConnectorBundleLoaderFactory {\n"; + s += " private Set<String> eagerConnectors = new HashSet<String>();\n"; + s += " {\n"; + for (String c : usedConnectors) { + s += " eagerConnectors.add(" + c + + ".class.getName());\n"; + } + s += " }\n"; + s += "\n"; + s += " @Override\n"; + s += " protected LoadStyle getLoadStyle(JClassType connectorType) {\n"; + s += " if (eagerConnectors.contains(connectorType.getQualifiedBinaryName())) {\n"; + s += " return LoadStyle.EAGER;\n"; + s += " } else {\n"; + s += " // Loads all other connectors immediately after the initial view has\n"; + s += " // been rendered\n"; + s += " return LoadStyle.DEFERRED;\n"; + s += " }\n"; + s += " }\n"; + s += "}\n"; + + return s; + } + +} diff --git a/client/src/com/vaadin/client/debug/internal/SelectConnectorListener.java b/client/src/com/vaadin/client/debug/internal/SelectConnectorListener.java new file mode 100644 index 0000000000..409f9d14ce --- /dev/null +++ b/client/src/com/vaadin/client/debug/internal/SelectConnectorListener.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.debug.internal; + +import com.google.gwt.user.client.Element; +import com.vaadin.client.ServerConnector; + +/** + * Listener for the selection of a connector in the debug window. + * + * @since 7.1.4 + */ +public interface SelectConnectorListener { + /** + * Listener method called when a connector has been selected. If a specific + * element of the connector was selected, it is also given. + * + * @param connector + * selected connector + * @param element + * selected element of the connector or null if unknown + */ + public void select(ServerConnector connector, Element element); +}
\ No newline at end of file diff --git a/client/src/com/vaadin/client/debug/internal/SelectorPath.java b/client/src/com/vaadin/client/debug/internal/SelectorPath.java new file mode 100644 index 0000000000..b8732e134e --- /dev/null +++ b/client/src/com/vaadin/client/debug/internal/SelectorPath.java @@ -0,0 +1,238 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.debug.internal; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.gwt.user.client.Element; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.componentlocator.ComponentLocator; +import com.vaadin.client.componentlocator.SelectorPredicate; + +/** + * A single segment of a selector path pointing to an Element. + * <p> + * This class should be considered internal to the framework and may change at + * any time. + * <p> + * + * @since 7.1.x + */ +public class SelectorPath { + private final String path; + private final Element element; + private final ComponentLocator locator; + private static Map<String, Integer> counter = new HashMap<String, Integer>(); + private static Map<String, String> legacyNames = new HashMap<String, String>(); + + static { + legacyNames.put("FilterSelect", "ComboBox"); + legacyNames.put("ScrollTable", "Table"); + } + + protected SelectorPath(ServerConnector c, Element e) { + element = e; + locator = new ComponentLocator(c.getConnection()); + path = locator.getPathForElement(e); + } + + public String getPath() { + return path; + } + + public Element getElement() { + return element; + } + + public ComponentLocator getLocator() { + return locator; + } + + /** + * Generate ElementQuery code for Java. Fallback to By.vaadin(path) if + * dealing with LegacyLocator + * + * @return String containing Java code for finding the element described by + * path + */ + public String getElementQuery() { + if (locator.isValidForLegacyLocator(path)) { + return getLegacyLocatorQuery(); + } + + String[] fragments; + String tmpPath = path; + List<SelectorPredicate> postFilters = SelectorPredicate + .extractPostFilterPredicates(path); + if (postFilters.size() > 0) { + tmpPath = tmpPath.substring(1, tmpPath.lastIndexOf(')')); + } + + // Generate an ElementQuery + fragments = tmpPath.split("/"); + String elementQueryString; + int index = 0; + for (SelectorPredicate p : postFilters) { + if (p.getIndex() > 0) { + index = p.getIndex(); + } + } + if (index > 0) { + elementQueryString = ".get(" + index + ");"; + } else { + elementQueryString = ".first();"; + } + for (int i = 1; i < fragments.length; ++i) { + if (fragments[i].isEmpty()) { + // Recursive search has occasional empty fragments + continue; + } + + // Get Element.class -name + String queryFragment = ""; + String elementClass = getComponentName(fragments[i]) + + "Element.class"; + for (SelectorPredicate p : SelectorPredicate + .extractPredicates(fragments[i])) { + // Add in predicates like .caption and .id + queryFragment += "." + p.getName() + "(\"" + p.getValue() + + "\")"; + } + if (i == fragments.length - 1) { + // Last element in path. + queryFragment = "$(" + elementClass + ")" + queryFragment; + } else { + // If followed by an empty fragment search is recursive + boolean recursive = fragments[i + 1].isEmpty(); + if (recursive) { + queryFragment = ".in(" + elementClass + ")" + queryFragment; + } else { + queryFragment = ".childOf(" + elementClass + ")" + + queryFragment; + } + } + elementQueryString = queryFragment + elementQueryString; + } + + if (!tmpPath.startsWith("//")) { + elementQueryString = "$" + elementQueryString; + } + + // Return full Java variable assignment and eQuery + return generateJavaVariable(fragments[fragments.length - 1]) + + elementQueryString; + } + + /** + * @since + * @param frags + * @param i + * @return + */ + protected String getComponentName(String fragment) { + return fragment.split("\\[")[0]; + } + + /** + * Generates a legacy locator for SelectorPath. + * + * @return String containing Java code for element search and assignment + */ + private String getLegacyLocatorQuery() { + String[] frags = path.split("/"); + String name = getComponentName(frags[frags.length - 1]).substring(1); + + if (legacyNames.containsKey(name)) { + name = legacyNames.get(name); + } + + name = getNameWithCount(name); + + // Use direct path and elementX naming style. + return "WebElement " + name.substring(0, 1).toLowerCase() + + name.substring(1) + " = getDriver().findElement(By.vaadin(\"" + + path + "\"));"; + } + + /** + * Get variable name with counter for given component name. + * + * @param name + * Component name + * @return name followed by count + */ + protected String getNameWithCount(String name) { + if (!counter.containsKey(name)) { + counter.put(name, 0); + } + counter.put(name, counter.get(name) + 1); + name += counter.get(name); + return name; + } + + /** + * Generate Java variable assignment from given selector fragment + * + * @param pathFragment + * Selector fragment + * @return piece of java code + */ + private String generateJavaVariable(String pathFragment) { + // Get element type and predicates from fragment + List<SelectorPredicate> predicates = SelectorPredicate + .extractPredicates(pathFragment); + String elementType = pathFragment.split("\\[")[0]; + String name = getNameFromPredicates(predicates, elementType); + + if (name.equals(elementType)) { + name = getNameWithCount(name); + } + + // Replace unusable characters + name = name.replaceAll("\\W", ""); + + // Lowercase the first character of name + return elementType + "Element " + name.substring(0, 1).toLowerCase() + + name.substring(1) + " = "; + } + + /** + * Get variable name based on predicates. Fallback to elementType + * + * @param predicates + * Predicates related to element + * @param elementType + * Element type + * @return name for Variable + */ + private String getNameFromPredicates(List<SelectorPredicate> predicates, + String elementType) { + String name = elementType; + for (SelectorPredicate p : predicates) { + if ("caption".equals(p.getName())) { + // Caption + elementType is a suitable name + name = p.getValue() + elementType; + } else if ("id".equals(p.getName())) { + // Just id. This is unique, use it. + return p.getValue(); + } + } + return name; + } +}
\ No newline at end of file diff --git a/client/src/com/vaadin/client/debug/internal/TestBenchSection.java b/client/src/com/vaadin/client/debug/internal/TestBenchSection.java new file mode 100644 index 0000000000..5be75f2003 --- /dev/null +++ b/client/src/com/vaadin/client/debug/internal/TestBenchSection.java @@ -0,0 +1,281 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.client.debug.internal; + +import java.util.HashMap; +import java.util.Map; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.dom.client.MouseOutEvent; +import com.google.gwt.event.dom.client.MouseOutHandler; +import com.google.gwt.event.dom.client.MouseOverEvent; +import com.google.gwt.event.dom.client.MouseOverHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Event.NativePreviewEvent; +import com.google.gwt.user.client.Event.NativePreviewHandler; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.RootPanel; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ApplicationConfiguration; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.Util; +import com.vaadin.client.ValueMap; + +/** + * Provides functionality for picking selectors for Vaadin TestBench. + * + * @since 7.1.x + * @author Vaadin Ltd + */ +public class TestBenchSection implements Section { + + /** + * Selector widget showing a selector in a program-usable form. + */ + private static class SelectorWidget extends HTML implements + MouseOverHandler, MouseOutHandler { + private final SelectorPath path; + + public SelectorWidget(final SelectorPath path) { + this.path = path; + + String html = "<div class=\"" + VDebugWindow.STYLENAME + + "-selector\"><span class=\"tb-selector\">" + + Util.escapeHTML(path.getElementQuery()) + "</span></div>"; + setHTML(html); + + addMouseOverHandler(this); + addMouseOutHandler(this); + } + + @Override + public void onMouseOver(MouseOverEvent event) { + Highlight.hideAll(); + + Element element = path.getElement(); + if (null != element) { + Highlight.show(element); + } + } + + @Override + public void onMouseOut(MouseOutEvent event) { + Highlight.hideAll(); + } + } + + private final DebugButton tabButton = new DebugButton(Icon.WARNING, + "Pick Vaadin TestBench selectors"); + + private final FlowPanel content = new FlowPanel(); + + private final FlowPanel selectorPanel = new FlowPanel(); + // map from full path to SelectorWidget to enable reuse of old selectors + private Map<SelectorPath, SelectorWidget> selectorWidgets = new HashMap<SelectorPath, SelectorWidget>(); + + private final FlowPanel controls = new FlowPanel(); + + private final Button find = new DebugButton(Icon.HIGHLIGHT, + "Pick an element and generate a query for it"); + + private final Button clear = new DebugButton(Icon.CLEAR, + "Clear current elements"); + + private HandlerRegistration highlightModeRegistration = null; + + public TestBenchSection() { + + controls.add(find); + find.setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON); + find.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + toggleFind(); + } + }); + + controls.add(clear); + clear.setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON); + clear.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + clearResults(); + } + }); + + content.setStylePrimaryName(VDebugWindow.STYLENAME + "-testbench"); + content.add(selectorPanel); + } + + @Override + public DebugButton getTabButton() { + return tabButton; + } + + @Override + public Widget getControls() { + return controls; + } + + @Override + public Widget getContent() { + return content; + } + + @Override + public void show() { + + } + + @Override + public void hide() { + stopFind(); + } + + @Override + public void meta(ApplicationConnection ac, ValueMap meta) { + // NOP + } + + @Override + public void uidl(ApplicationConnection ac, ValueMap uidl) { + // NOP + } + + private boolean isFindMode() { + return (highlightModeRegistration != null); + } + + private void toggleFind() { + if (isFindMode()) { + stopFind(); + } else { + startFind(); + } + } + + private void startFind() { + Highlight.hideAll(); + if (!isFindMode()) { + highlightModeRegistration = Event + .addNativePreviewHandler(highlightModeHandler); + find.addStyleDependentName(VDebugWindow.STYLENAME_ACTIVE); + } + } + + private void stopFind() { + if (isFindMode()) { + highlightModeRegistration.removeHandler(); + highlightModeRegistration = null; + find.removeStyleDependentName(VDebugWindow.STYLENAME_ACTIVE); + } + Highlight.hideAll(); + } + + private void pickSelector(ServerConnector connector, Element element) { + + SelectorPath p = new SelectorPath(connector, Util + .findPaintable(connector.getConnection(), element).getWidget() + .getElement()); + SelectorWidget w = new SelectorWidget(p); + + content.add(w); + } + + private final NativePreviewHandler highlightModeHandler = new NativePreviewHandler() { + + @Override + public void onPreviewNativeEvent(NativePreviewEvent event) { + + if (event.getTypeInt() == Event.ONKEYDOWN + && event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) { + stopFind(); + Highlight.hideAll(); + return; + } + if (event.getTypeInt() == Event.ONMOUSEMOVE + || event.getTypeInt() == Event.ONCLICK) { + Element eventTarget = Util.getElementFromPoint(event + .getNativeEvent().getClientX(), event.getNativeEvent() + .getClientY()); + if (VDebugWindow.get().getElement().isOrHasChild(eventTarget)) { + if (isFindMode() && event.getTypeInt() == Event.ONCLICK) { + stopFind(); + event.cancel(); + } + return; + } + + // make sure that not finding the highlight element only + Highlight.hideAll(); + + eventTarget = Util.getElementFromPoint(event.getNativeEvent() + .getClientX(), event.getNativeEvent().getClientY()); + ComponentConnector connector = findConnector(eventTarget); + + if (event.getTypeInt() == Event.ONMOUSEMOVE) { + if (connector != null) { + Highlight.showOnly(connector); + event.cancel(); + event.consume(); + event.getNativeEvent().stopPropagation(); + return; + } + } else if (event.getTypeInt() == Event.ONCLICK) { + event.cancel(); + event.consume(); + event.getNativeEvent().stopPropagation(); + if (connector != null) { + Highlight.showOnly(connector); + pickSelector(connector, eventTarget); + return; + } + } + } + event.cancel(); + } + + }; + + private ComponentConnector findConnector(Element element) { + for (ApplicationConnection a : ApplicationConfiguration + .getRunningApplications()) { + ComponentConnector connector = Util.getConnectorForElement(a, a + .getUIConnector().getWidget(), element); + if (connector == null) { + connector = Util.getConnectorForElement(a, RootPanel.get(), + element); + } + if (connector != null) { + return connector; + } + } + return null; + } + + private void clearResults() { + content.clear(); + } + +} diff --git a/client/src/com/vaadin/client/metadata/ConnectorBundleLoader.java b/client/src/com/vaadin/client/metadata/ConnectorBundleLoader.java index f1a9fa1ee7..8148010b54 100644 --- a/client/src/com/vaadin/client/metadata/ConnectorBundleLoader.java +++ b/client/src/com/vaadin/client/metadata/ConnectorBundleLoader.java @@ -15,11 +15,10 @@ */ package com.vaadin.client.metadata; -import java.util.HashMap; import java.util.List; -import java.util.Map; import com.google.gwt.core.shared.GWT; +import com.vaadin.client.FastStringMap; import com.vaadin.client.metadata.AsyncBundleLoader.State; public abstract class ConnectorBundleLoader { @@ -28,8 +27,9 @@ public abstract class ConnectorBundleLoader { private static ConnectorBundleLoader impl; - private Map<String, AsyncBundleLoader> asyncBlockLoaders = new HashMap<String, AsyncBundleLoader>(); - private Map<String, String> identifierToBundle = new HashMap<String, String>(); + private FastStringMap<AsyncBundleLoader> asyncBlockLoaders = FastStringMap + .create(); + private FastStringMap<String> identifierToBundle = FastStringMap.create(); private final TypeDataStore datStore = new TypeDataStore(); diff --git a/client/src/com/vaadin/client/metadata/Property.java b/client/src/com/vaadin/client/metadata/Property.java index 2e0ea49c88..64fbb79ca1 100644 --- a/client/src/com/vaadin/client/metadata/Property.java +++ b/client/src/com/vaadin/client/metadata/Property.java @@ -30,11 +30,11 @@ public class Property { } public Object getValue(Object bean) throws NoDataException { - return TypeDataStore.getGetter(this).invoke(bean); + return TypeDataStore.getValue(this, bean); } public void setValue(Object bean, Object value) throws NoDataException { - TypeDataStore.getSetter(this).invoke(bean, value); + TypeDataStore.setValue(this, bean, value); } public String getDelegateToWidgetMethodName() { @@ -50,6 +50,10 @@ public class Property { return TypeDataStore.getType(this); } + public Type getBeanType() { + return bean; + } + /** * The unique signature used to identify this property. The structure of the * returned string may change without notice and should not be used for any diff --git a/client/src/com/vaadin/client/metadata/TypeDataStore.java b/client/src/com/vaadin/client/metadata/TypeDataStore.java index aa37d75dc8..a3939b7994 100644 --- a/client/src/com/vaadin/client/metadata/TypeDataStore.java +++ b/client/src/com/vaadin/client/metadata/TypeDataStore.java @@ -34,8 +34,6 @@ public class TypeDataStore { .create(); private final FastStringMap<ProxyHandler> proxyHandlers = FastStringMap .create(); - private final FastStringMap<JsArrayObject<Property>> properties = FastStringMap - .create(); private final FastStringMap<JsArrayString> delegateToWidgetProperties = FastStringMap .create(); @@ -46,12 +44,11 @@ public class TypeDataStore { private final FastStringMap<Invoker> invokers = FastStringMap.create(); private final FastStringMap<Type[]> paramTypes = FastStringMap.create(); - private final FastStringMap<Type> propertyTypes = FastStringMap.create(); - private final FastStringMap<Invoker> setters = FastStringMap.create(); - private final FastStringMap<Invoker> getters = FastStringMap.create(); private final FastStringMap<String> delegateToWidget = FastStringMap .create(); + private final JavaScriptObject jsTypeData = JavaScriptObject.createObject(); + public static TypeDataStore get() { return ConnectorBundleLoader.get().getTypeDataStore(); } @@ -69,6 +66,22 @@ public class TypeDataStore { return class1; } + // this is a very inefficient implementation for getting all the identifiers + // for a class + public FastStringSet findIdentifiersFor(Class<?> type) { + FastStringSet result = FastStringSet.create(); + + JsArrayString keys = identifiers.getKeys(); + for (int i = 0; i < keys.length(); i++) { + String key = keys.get(i); + if (identifiers.get(key) == type) { + result.add(key); + } + } + + return result; + } + public static Type getType(Class<?> clazz) { return new Type(clazz); } @@ -101,19 +114,10 @@ public class TypeDataStore { return invoker; } - public static Invoker getGetter(Property property) throws NoDataException { - Invoker getter = get().getters.get(property.getSignature()); - if (getter == null) { - throw new NoDataException("There is no getter for " - + property.getSignature()); - } - - return getter; - } - - public void setGetter(Class<?> clazz, String propertyName, Invoker invoker) { - getters.put(new Property(getType(clazz), propertyName).getSignature(), - invoker); + public static Object getValue(Property property, Object target) + throws NoDataException { + return getJsPropertyValue(get().jsTypeData, property.getBeanType() + .getBaseTypeName(), property.getName(), target); } public static String getDelegateToWidget(Property property) { @@ -227,51 +231,31 @@ public class TypeDataStore { public static JsArrayObject<Property> getPropertiesAsArray(Type type) throws NoDataException { - JsArrayObject<Property> properties = get().properties.get(type - .getSignature()); - if (properties == null) { - throw new NoDataException("No property list for " - + type.getSignature()); - } - return properties; - } + JsArrayString names = getJsPropertyNames(get().jsTypeData, + type.getBaseTypeName()); - public void setProperties(Class<?> clazz, String[] propertyNames) { + // Create Property instances for each property name JsArrayObject<Property> properties = JavaScriptObject.createArray() .cast(); - Type type = getType(clazz); - for (String name : propertyNames) { - properties.add(new Property(type, name)); + for (int i = 0; i < names.length(); i++) { + properties.add(new Property(type, names.get(i))); } - this.properties.put(type.getSignature(), properties); - } - public static Type getType(Property property) throws NoDataException { - Type type = get().propertyTypes.get(property.getSignature()); - if (type == null) { - throw new NoDataException("No return type for " - + property.getSignature()); - } - return type; + return properties; } - public void setPropertyType(Class<?> clazz, String propertName, Type type) { - propertyTypes.put( - new Property(getType(clazz), propertName).getSignature(), type); + public static Type getType(Property property) throws NoDataException { + return getJsPropertyType(get().jsTypeData, property.getBeanType() + .getBaseTypeName(), property.getName()); } - public static Invoker getSetter(Property property) throws NoDataException { - Invoker setter = get().setters.get(property.getSignature()); - if (setter == null) { - throw new NoDataException("No setter for " - + property.getSignature()); - } - return setter; + public void setPropertyType(Class<?> clazz, String propertyName, Type type) { + setJsPropertyType(jsTypeData, clazz.getName(), propertyName, type); } - public void setSetter(Class<?> clazz, String propertyName, Invoker setter) { - setters.put(new Property(getType(clazz), propertyName).getSignature(), - setter); + public static void setValue(Property property, Object target, Object value) { + setJsPropertyValue(get().jsTypeData, property.getBeanType() + .getBaseTypeName(), property.getName(), target, value); } public void setSerializerFactory(Class<?> clazz, Invoker factory) { @@ -288,6 +272,99 @@ public class TypeDataStore { } public static boolean hasProperties(Type type) { - return get().properties.containsKey(type.getSignature()); + return hasJsProperties(get().jsTypeData, type.getBaseTypeName()); } + + public void setSuperClass(Class<?> baseClass, Class<?> superClass) { + String superClassName = superClass == null ? null : superClass + .getName(); + setSuperClass(jsTypeData, baseClass.getName(), superClassName); + } + + public void setPropertyData(Class<?> type, String propertyName, + JavaScriptObject propertyData) { + setPropertyData(jsTypeData, type.getName(), propertyName, propertyData); + } + + private static native void setPropertyData(JavaScriptObject typeData, + String className, String propertyName, JavaScriptObject propertyData) + /*-{ + typeData[className][propertyName] = propertyData; + }-*/; + + /* + * This method sets up prototypes chain for <code>baseClassName</code>. + * Precondition is : <code>superClassName</code> had to be handled before + * its child <code>baseClassName</code>. + * + * It makes all properties defined in the <code>superClassName</code> + * available for <code>baseClassName</code> as well. + */ + private static native void setSuperClass(JavaScriptObject typeData, + String baseClassName, String superClassName) + /*-{ + var parentType = typeData[superClassName]; + if (parentType !== undefined ){ + var ctor = function () {}; + ctor.prototype = parentType; + typeData[baseClassName] = new ctor; + } + else { + typeData[baseClassName] = {}; + } + }-*/; + + private static native boolean hasGetter(JavaScriptObject typeData, + String beanName, String propertyName) + /*-{ + return typeData[beanName][propertyName].getter !== undefined; + }-*/; + + private static native boolean hasSetter(JavaScriptObject typeData, + String beanName, String propertyName) + /*-{ + return typeData[beanName][propertyName].setter !== undefined; + }-*/; + + private static native Object getJsPropertyValue(JavaScriptObject typeData, + String beanName, String propertyName, Object beanInstance) + /*-{ + return typeData[beanName][propertyName].getter(beanInstance); + }-*/; + + private static native void setJsPropertyValue(JavaScriptObject typeData, + String beanName, String propertyName, Object beanInstance, + Object value) + /*-{ + typeData[beanName][propertyName].setter(beanInstance, value); + }-*/; + + private static native Type getJsPropertyType(JavaScriptObject typeData, + String beanName, String propertyName) + /*-{ + return typeData[beanName][propertyName].type; + }-*/; + + private static native void setJsPropertyType(JavaScriptObject typeData, + String beanName, String propertyName, Type type) + /*-{ + typeData[beanName][propertyName].type = type; + }-*/; + + private static native JsArrayString getJsPropertyNames( + JavaScriptObject typeData, String beanName) + /*-{ + var names = []; + for(var name in typeData[beanName]) { + names.push(name); + } + return names; + }-*/; + + private static native boolean hasJsProperties(JavaScriptObject typeData, + String beanName) + /*-{ + return typeData[beanName] !== undefined ; + }-*/; + } diff --git a/client/src/com/vaadin/client/ui/SubPartAware.java b/client/src/com/vaadin/client/ui/SubPartAware.java index a7d72fab01..36959e7b1f 100644 --- a/client/src/com/vaadin/client/ui/SubPartAware.java +++ b/client/src/com/vaadin/client/ui/SubPartAware.java @@ -17,7 +17,7 @@ package com.vaadin.client.ui; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Widget; -import com.vaadin.client.ComponentLocator; +import com.vaadin.client.componentlocator.ComponentLocator; /** * Interface implemented by {@link Widget}s which can provide identifiers for at @@ -59,4 +59,4 @@ public interface SubPartAware { */ String getSubPartName(Element subElement); -}
\ No newline at end of file +} diff --git a/client/src/com/vaadin/client/ui/UnknownComponentConnector.java b/client/src/com/vaadin/client/ui/UnknownComponentConnector.java index ca461eb640..b9b0388d9a 100644 --- a/client/src/com/vaadin/client/ui/UnknownComponentConnector.java +++ b/client/src/com/vaadin/client/ui/UnknownComponentConnector.java @@ -16,6 +16,8 @@ package com.vaadin.client.ui; +import com.google.gwt.core.client.GWT; + public class UnknownComponentConnector extends AbstractComponentConnector { @Override @@ -31,7 +33,9 @@ public class UnknownComponentConnector extends AbstractComponentConnector { public void setServerSideClassName(String serverClassName) { getWidget() .setCaption( - "Widgetset does not contain implementation for " + "Widgetset '" + + GWT.getModuleName() + + "' does not contain implementation for " + serverClassName + ". Check its component connector's @Connect mapping, widgetsets " + "GWT module description file and re-compile your" diff --git a/client/src/com/vaadin/client/ui/VAccordion.java b/client/src/com/vaadin/client/ui/VAccordion.java index f87186fe37..ddfe9dbc2c 100644 --- a/client/src/com/vaadin/client/ui/VAccordion.java +++ b/client/src/com/vaadin/client/ui/VAccordion.java @@ -463,7 +463,6 @@ public class VAccordion extends VTabsheetBase { } @Override - @SuppressWarnings("unchecked") public Iterator<Widget> getWidgetIterator() { return widgets.iterator(); } diff --git a/client/src/com/vaadin/client/ui/VCalendarPanel.java b/client/src/com/vaadin/client/ui/VCalendarPanel.java index 96678fd133..b043cd0ab7 100644 --- a/client/src/com/vaadin/client/ui/VCalendarPanel.java +++ b/client/src/com/vaadin/client/ui/VCalendarPanel.java @@ -170,8 +170,6 @@ public class VCalendarPanel extends FocusableFlexTable implements private Resolution resolution = Resolution.YEAR; - private int focusedRow; - private Timer mouseTimer; private Date value; @@ -256,7 +254,6 @@ public class VCalendarPanel extends FocusableFlexTable implements if (curday.getDate().equals(date)) { curday.addStyleDependentName(CN_FOCUSED); focusedDay = curday; - focusedRow = i; return; } } @@ -741,7 +738,6 @@ public class VCalendarPanel extends FocusableFlexTable implements } if (curr.equals(focusedDate)) { focusedDay = day; - focusedRow = weekOfMonth; if (hasFocus) { day.addStyleDependentName(CN_FOCUSED); } @@ -1795,10 +1791,8 @@ public class VCalendarPanel extends FocusableFlexTable implements * Updates the valus to correspond to the values in value */ public void updateTimes() { - boolean selected = true; if (value == null) { value = new Date(); - selected = false; } if (getDateTimeService().isTwelveHourClock()) { int h = value.getHours(); @@ -1833,10 +1827,6 @@ public class VCalendarPanel extends FocusableFlexTable implements } - private int getMilliseconds() { - return DateTimeService.getMilliseconds(value); - } - private DateTimeService getDateTimeService() { if (dateTimeService == null) { dateTimeService = new DateTimeService(); @@ -2034,7 +2024,6 @@ public class VCalendarPanel extends FocusableFlexTable implements private static final String SUBPART_HOUR_SELECT = "h"; private static final String SUBPART_MINUTE_SELECT = "m"; private static final String SUBPART_SECS_SELECT = "s"; - private static final String SUBPART_MSECS_SELECT = "ms"; private static final String SUBPART_AMPM_SELECT = "ampm"; private static final String SUBPART_DAY = "day"; private static final String SUBPART_MONTH_YEAR_HEADER = "header"; diff --git a/client/src/com/vaadin/client/ui/VFilterSelect.java b/client/src/com/vaadin/client/ui/VFilterSelect.java index 7efb5b8867..9bace9141c 100644 --- a/client/src/com/vaadin/client/ui/VFilterSelect.java +++ b/client/src/com/vaadin/client/ui/VFilterSelect.java @@ -1988,6 +1988,8 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, return tb.getElement(); } else if ("button".equals(subPart)) { return popupOpener.getElement(); + } else if ("popup".equals(subPart) && suggestionPopup.isAttached()) { + return suggestionPopup.getElement(); } return null; } @@ -1998,6 +2000,8 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, return "textbox"; } else if (popupOpener.getElement().isOrHasChild(subElement)) { return "button"; + } else if (suggestionPopup.getElement().isOrHasChild(subElement)) { + return "popup"; } return null; } diff --git a/client/src/com/vaadin/client/ui/VLabel.java b/client/src/com/vaadin/client/ui/VLabel.java index 8acd653778..35f47d540a 100644 --- a/client/src/com/vaadin/client/ui/VLabel.java +++ b/client/src/com/vaadin/client/ui/VLabel.java @@ -18,7 +18,6 @@ package com.vaadin.client.ui; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.HTML; -import com.vaadin.client.ApplicationConnection; import com.vaadin.client.BrowserInfo; import com.vaadin.client.Util; import com.vaadin.client.VTooltip; @@ -28,8 +27,6 @@ public class VLabel extends HTML { public static final String CLASSNAME = "v-label"; private static final String CLASSNAME_UNDEFINED_WIDTH = "v-label-undef-w"; - private ApplicationConnection connection; - public VLabel() { super(); setStyleName(CLASSNAME); @@ -71,9 +68,4 @@ public class VLabel extends HTML { super.setText(text); } } - - /** For internal use only. May be removed or replaced in the future. */ - public void setConnection(ApplicationConnection client) { - connection = client; - } } diff --git a/client/src/com/vaadin/client/ui/VOverlay.java b/client/src/com/vaadin/client/ui/VOverlay.java index 9f84c16020..545af2ce83 100644 --- a/client/src/com/vaadin/client/ui/VOverlay.java +++ b/client/src/com/vaadin/client/ui/VOverlay.java @@ -241,10 +241,10 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { private void removeShadowIfPresent() { if (isShadowAttached()) { - shadow.removeFromParent(); - // Remove event listener from the shadow unsinkShadowEvents(); + + shadow.removeFromParent(); } } diff --git a/client/src/com/vaadin/client/ui/VPanel.java b/client/src/com/vaadin/client/ui/VPanel.java index 6b02f079d1..ffeacade46 100644 --- a/client/src/com/vaadin/client/ui/VPanel.java +++ b/client/src/com/vaadin/client/ui/VPanel.java @@ -170,7 +170,6 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner, public void onBrowserEvent(Event event) { super.onBrowserEvent(event); - final Element target = DOM.eventGetTarget(event); final int type = DOM.eventGetType(event); if (type == Event.ONKEYDOWN && shortcutHandler != null) { shortcutHandler.handleKeyboardEvent(event); diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 8bd875690b..bbf06bfec1 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -61,6 +61,8 @@ import com.google.gwt.event.dom.client.ScrollHandler; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.regexp.shared.MatchResult; +import com.google.gwt.regexp.shared.RegExp; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; @@ -123,7 +125,7 @@ import com.vaadin.shared.ui.table.TableConstants; */ public class VScrollTable extends FlowPanel implements HasWidgets, ScrollHandler, VHasDropHandler, FocusHandler, BlurHandler, Focusable, - ActionOwner { + ActionOwner, SubPartAware { public static final String STYLENAME = "v-table"; @@ -991,6 +993,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, if (scrollBody != null) { scrollBody.removeFromParent(); } + + // Without this call the scroll position is messed up in IE even after + // the lazy scroller has set the scroll position to the first visible + // item + scrollBodyPanel.getScrollPosition(); + scrollBody = createScrollBody(); scrollBody.renderInitialRows(rowData, uidl.getIntAttribute("firstrow"), @@ -1054,6 +1062,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, if (uidl.hasVariable("selected")) { final Set<String> selectedKeys = uidl .getStringArrayVariableAsSet("selected"); + removeUnselectedRowKeys(selectedKeys); + if (scrollBody != null) { Iterator<Widget> iterator = scrollBody.iterator(); while (iterator.hasNext()) { @@ -1096,6 +1106,16 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return keyboardSelectionOverRowFetchInProgress; } + private void removeUnselectedRowKeys(final Set<String> selectedKeys) { + List<String> unselectedKeys = new ArrayList<String>(0); + for (String key : selectedRowKeys) { + if (!selectedKeys.contains(key)) { + unselectedKeys.add(key); + } + } + selectedRowKeys.removeAll(unselectedKeys); + } + /** For internal use only. May be removed or replaced in the future. */ public void updateSortingProperties(UIDL uidl) { oldSortColumn = sortColumn; @@ -1121,7 +1141,28 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } } + private boolean lazyScrollerIsActive; + + private void disableLazyScroller() { + lazyScrollerIsActive = false; + scrollBodyPanel.getElement().getStyle().clearOverflowX(); + scrollBodyPanel.getElement().getStyle().clearOverflowY(); + } + + private void enableLazyScroller() { + Scheduler.get().scheduleDeferred(lazyScroller); + lazyScrollerIsActive = true; + // prevent scrolling to jump in IE11 + scrollBodyPanel.getElement().getStyle().setOverflowX(Overflow.HIDDEN); + scrollBodyPanel.getElement().getStyle().setOverflowY(Overflow.HIDDEN); + } + + private boolean isLazyScrollerActive() { + return lazyScrollerIsActive; + } + private ScheduledCommand lazyScroller = new ScheduledCommand() { + @Override public void execute() { if (firstvisible > 0) { @@ -1134,6 +1175,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, .setScrollPosition(measureRowHeightOffset(firstvisible)); } } + disableLazyScroller(); } }; @@ -1152,7 +1194,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // Only scroll if the first visible changes from the server side. // Else we might unintentionally scroll even when the scroll // position has not changed. - Scheduler.get().scheduleDeferred(lazyScroller); + enableLazyScroller(); } } @@ -2172,7 +2214,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, isNewBody = false; if (firstvisible > 0) { - Scheduler.get().scheduleDeferred(lazyScroller); + enableLazyScroller(); } if (enabled) { @@ -5056,6 +5098,20 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } } + public int indexOf(Widget row) { + int relIx = -1; + for (int ix = 0; ix < renderedRows.size(); ix++) { + if (renderedRows.get(ix) == row) { + relIx = ix; + break; + } + } + if (relIx >= 0) { + return this.firstRendered + relIx; + } + return -1; + } + public class VScrollTableRow extends Panel implements ActionOwner { private static final int TOUCHSCROLL_TIMEOUT = 100; @@ -6037,7 +6093,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private Element getEventTargetTdOrTr(Event event) { final Element eventTarget = event.getEventTarget().cast(); Widget widget = Util.findWidget(eventTarget, null); - final Element thisTrElement = getElement(); if (widget != this) { /* @@ -6884,6 +6939,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, @Override public void onScroll(ScrollEvent event) { + // Do not handle scroll events while there is scroll initiated from + // server side which is not yet executed (#11454) + if (isLazyScrollerActive()) { + return; + } + scrollLeft = scrollBodyPanel.getElement().getScrollLeft(); scrollTop = scrollBodyPanel.getScrollPosition(); /* @@ -6932,8 +6993,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } firstRowInViewPort = calcFirstRowInViewPort(); - if (firstRowInViewPort > totalRows - pageLength) { - firstRowInViewPort = totalRows - pageLength; + int maxFirstRow = totalRows - pageLength; + if (firstRowInViewPort > maxFirstRow && maxFirstRow >= 0) { + firstRowInViewPort = maxFirstRow; } int postLimit = (int) (firstRowInViewPort + (pageLength - 1) + pageLength @@ -7764,4 +7826,94 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return this; } + private static final String SUBPART_HEADER = "header"; + private static final String SUBPART_FOOTER = "footer"; + private static final String SUBPART_ROW = "row"; + private static final String SUBPART_COL = "col"; + /** Matches header[ix] - used for extracting the index of the targeted header cell */ + private static final RegExp SUBPART_HEADER_REGEXP = RegExp + .compile(SUBPART_HEADER + "\\[(\\d+)\\]"); + /** Matches footer[ix] - used for extracting the index of the targeted footer cell */ + private static final RegExp SUBPART_FOOTER_REGEXP = RegExp + .compile(SUBPART_FOOTER + "\\[(\\d+)\\]"); + /** Matches row[ix] - used for extracting the index of the targeted row */ + private static final RegExp SUBPART_ROW_REGEXP = RegExp.compile(SUBPART_ROW + + "\\[(\\d+)]"); + /** Matches col[ix] - used for extracting the index of the targeted column */ + private static final RegExp SUBPART_ROW_COL_REGEXP = RegExp + .compile(SUBPART_ROW + "\\[(\\d+)\\]/" + SUBPART_COL + "\\[(\\d+)\\]"); + + @Override + public Element getSubPartElement(String subPart) { + if (SUBPART_ROW_COL_REGEXP.test(subPart)) { + MatchResult result = SUBPART_ROW_COL_REGEXP.exec(subPart); + int rowIx = Integer.valueOf(result.getGroup(1)); + int colIx = Integer.valueOf(result.getGroup(2)); + VScrollTableRow row = scrollBody.getRowByRowIndex(rowIx); + if (row != null) { + Element rowElement = row.getElement(); + if (colIx < rowElement.getChildCount()) { + return rowElement.getChild(colIx).getFirstChild().cast(); + } + } + + } else if (SUBPART_ROW_REGEXP.test(subPart)) { + MatchResult result = SUBPART_ROW_REGEXP.exec(subPart); + int rowIx = Integer.valueOf(result.getGroup(1)); + VScrollTableRow row = scrollBody.getRowByRowIndex(rowIx); + if (row != null) { + return row.getElement(); + } + + } else if (SUBPART_HEADER_REGEXP.test(subPart)) { + MatchResult result = SUBPART_HEADER_REGEXP.exec(subPart); + int headerIx = Integer.valueOf(result.getGroup(1)); + HeaderCell headerCell = tHead.getHeaderCell(headerIx); + if (headerCell != null) { + return headerCell.getElement(); + } + + } else if (SUBPART_FOOTER_REGEXP.test(subPart)) { + MatchResult result = SUBPART_FOOTER_REGEXP.exec(subPart); + int footerIx = Integer.valueOf(result.getGroup(1)); + FooterCell footerCell = tFoot.getFooterCell(footerIx); + if (footerCell != null) { + return footerCell.getElement(); + } + } + // Nothing found. + return null; + } + + @Override + public String getSubPartName(Element subElement) { + Widget widget = Util.findWidget(subElement, null); + if (widget instanceof HeaderCell) { + return SUBPART_HEADER + "[" + tHead.visibleCells.indexOf(widget) + + "]"; + } else if (widget instanceof FooterCell) { + return SUBPART_FOOTER + "[" + tFoot.visibleCells.indexOf(widget) + + "]"; + } else if (widget instanceof VScrollTableRow) { + // a cell in a row + VScrollTableRow row = (VScrollTableRow) widget; + int rowIx = scrollBody.indexOf(row); + if (rowIx >= 0) { + int colIx = -1; + for (int ix = 0; ix < row.getElement().getChildCount(); ix++) { + if (row.getElement().getChild(ix).isOrHasChild(subElement)) { + colIx = ix; + break; + } + } + if (colIx >= 0) { + return SUBPART_ROW + "[" + rowIx + "]/" + SUBPART_COL + "[" + + colIx + "]"; + } + return SUBPART_ROW + "[" + rowIx + "]"; + } + } + // Nothing found. + return null; + } } diff --git a/client/src/com/vaadin/client/ui/VTabsheet.java b/client/src/com/vaadin/client/ui/VTabsheet.java index 9ad518b85b..82eb9e7694 100644 --- a/client/src/com/vaadin/client/ui/VTabsheet.java +++ b/client/src/com/vaadin/client/ui/VTabsheet.java @@ -135,7 +135,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, SelectedValue.FALSE); div = DOM.createDiv(); - focusImpl.setTabIndex(td, -1); + setTabulatorIndex(-1); setStyleName(div, DIV_CLASSNAME); DOM.appendChild(td, div); @@ -213,7 +213,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } public void setTabulatorIndex(int tabIndex) { - focusImpl.setTabIndex(td, tabIndex); + getElement().setTabIndex(tabIndex); } public boolean isClosable() { @@ -313,11 +313,9 @@ public class VTabsheet extends VTabsheetBase implements Focusable, private boolean closable = false; private Element closeButton; private Tab tab; - private ApplicationConnection client; TabCaption(Tab tab, ApplicationConnection client) { super(client); - this.client = client; this.tab = tab; AriaHelper.ensureHasId(getElement()); @@ -488,6 +486,9 @@ public class VTabsheet extends VTabsheetBase implements Focusable, int index = getWidgetIndex(caption.getParent()); + navigateTab(getTabsheet().focusedTabIndex, index); + getTabsheet().focusedTabIndex = index; + getTabsheet().focusedTab = getTab(index); getTabsheet().focus(); getTabsheet().loadTabSheet(index); } @@ -702,15 +703,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, if (activeTabIndex != tabIndex && canSelectTab(tabIndex)) { tb.selectTab(tabIndex); - // If this TabSheet already has focus, set the new selected tab - // as focused. - if (focusedTab != null) { - focusedTab = tb.getTab(tabIndex); - focusedTab.focus(); - } - activeTabIndex = tabIndex; - focusedTabIndex = tabIndex; addStyleDependentName("loading"); // Hide the current contents so a loading indicator can be shown @@ -722,6 +715,8 @@ public class VTabsheet extends VTabsheetBase implements Focusable, client.updateVariable(id, "selected", tabKeys.get(tabIndex) .toString(), true); waitingForResponse = true; + + tb.getTab(tabIndex).focus(); // move keyboard focus to active tab } } @@ -952,6 +947,10 @@ public class VTabsheet extends VTabsheetBase implements Focusable, if (tab == null) { tab = tb.addTab(); } + if (selected) { + tb.selectTab(index); + renderContent(tabUidl.getChildUIDL(0)); + } tab.updateFromUIDL(tabUidl); tab.setEnabledOnServer((!disabledTabKeys.contains(tabKeys.get(index)))); tab.setHiddenOnServer(hidden); @@ -968,11 +967,6 @@ public class VTabsheet extends VTabsheetBase implements Focusable, * and tabs won't be too narrow in certain browsers */ tab.recalculateCaptionWidth(); - - if (selected) { - renderContent(tabUidl.getChildUIDL(0)); - tb.selectTab(index); - } } /** @@ -1089,16 +1083,18 @@ public class VTabsheet extends VTabsheetBase implements Focusable, SCROLLER_CLASSNAME + (scrolled ? "Prev" : "Prev-disabled")); DOM.setElementProperty(scrollerNext, "className", SCROLLER_CLASSNAME + (clipped ? "Next" : "Next-disabled")); + + // the active tab should be focusable if and only if it is visible + boolean isActiveTabVisible = scrollerIndex <= activeTabIndex + && !isClipped(tb.selected); + tb.selected.setTabulatorIndex(isActiveTabVisible ? tabulatorIndex + : -1); + } else { DOM.setStyleAttribute(scroller, "display", "none"); } if (BrowserInfo.get().isSafari()) { - // fix tab height for safari, bugs sometimes if tabs contain icons - String property = tabs.getStyle().getProperty("height"); - if (property == null || property.equals("")) { - tabs.getStyle().setPropertyPx("height", tb.getOffsetHeight()); - } /* * another hack for webkits. tabscroller sometimes drops without * "shaking it" reproducable in @@ -1194,7 +1190,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, public void onBlur(BlurEvent event) { getApplicationConnection().getVTooltip().hideTooltip(); - if (focusedTab != null && event.getSource() instanceof Tab) { + if (focusedTab != null && focusedTab == event.getSource()) { focusedTab.removeAssistiveDescription(); focusedTab = null; if (client.hasEventListeners(this, EventId.BLUR)) { @@ -1300,13 +1296,10 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } if (isScrolledTabs()) { - // Scroll until the new active tab is visible - int newScrollerIndex = scrollerIndex; - while (tb.getTab(focusedTabIndex).getAbsoluteLeft() < getAbsoluteLeft() - && newScrollerIndex != -1) { - newScrollerIndex = tb.scrollLeft(newScrollerIndex); + // Scroll until the new focused tab is visible + while (!tb.getTab(focusedTabIndex).isVisible()) { + scrollerIndex = tb.scrollLeft(scrollerIndex); } - scrollerIndex = newScrollerIndex; updateTabScroller(); } } diff --git a/client/src/com/vaadin/client/ui/VTreeTable.java b/client/src/com/vaadin/client/ui/VTreeTable.java index 097b9c7ab2..54c9c2d30c 100644 --- a/client/src/com/vaadin/client/ui/VTreeTable.java +++ b/client/src/com/vaadin/client/ui/VTreeTable.java @@ -131,7 +131,7 @@ public class VTreeTable extends VScrollTable { private int indentWidth = -1; private int maxIndent = 0; - VTreeTableScrollBody() { + protected VTreeTableScrollBody() { super(); } diff --git a/client/src/com/vaadin/client/ui/VUpload.java b/client/src/com/vaadin/client/ui/VUpload.java index c08d75e9b7..8e55387d39 100644 --- a/client/src/com/vaadin/client/ui/VUpload.java +++ b/client/src/com/vaadin/client/ui/VUpload.java @@ -295,10 +295,13 @@ public class VUpload extends SimplePanel { /** For internal use only. May be removed or replaced in the future. */ public void submit() { - if (fu.getFilename().length() == 0 || submitted || !enabled) { - VConsole.log("Submit cancelled (disabled, no file or already submitted)"); + if (submitted || !enabled) { + VConsole.log("Submit cancelled (disabled or already submitted)"); return; } + if (fu.getFilename().length() == 0) { + VConsole.log("Submitting empty selection (no file)"); + } // flush possibly pending variable changes, so they will be handled // before upload client.sendPendingVariableChanges(); diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java index 964adfe303..705787d6c8 100644 --- a/client/src/com/vaadin/client/ui/VWindow.java +++ b/client/src/com/vaadin/client/ui/VWindow.java @@ -27,6 +27,7 @@ import com.google.gwt.aria.client.RelevantValue; import com.google.gwt.aria.client.Roles; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Position; @@ -83,6 +84,8 @@ public class VWindow extends VWindowOverlay implements public static final String CLASSNAME = "v-window"; + private static final String MODAL_WINDOW_OPEN_CLASSNAME = "v-modal-window-open"; + private static final int STACKING_OFFSET_PIXELS = 15; public static final int Z_INDEX = 10000; @@ -725,10 +728,14 @@ public class VWindow extends VWindowOverlay implements getOverlayContainer().appendChild(getModalityCurtain()); } + Document.get().getBody().addClassName(MODAL_WINDOW_OPEN_CLASSNAME); } private void hideModalityCurtain() { + Document.get().getBody().removeClassName(MODAL_WINDOW_OPEN_CLASSNAME); + modalityCurtain.removeFromParent(); + if (BrowserInfo.get().isIE()) { // IE leaks memory in certain cases unless we release the reference // (#9197) diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java b/client/src/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java index 39de122694..344b5ce739 100644 --- a/client/src/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java +++ b/client/src/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java @@ -42,7 +42,6 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.HorizontalPanel; import com.vaadin.client.Util; -import com.vaadin.client.ui.VCalendar; import com.vaadin.shared.ui.calendar.DateConstants; /** @@ -105,7 +104,6 @@ public class DateCellDayEvent extends FocusableHTML implements eventContent.addClassName("v-calendar-event-content"); getElement().appendChild(eventContent); - VCalendar calendar = weekGrid.getCalendar(); if (weekGrid.getCalendar().isEventResizeAllowed()) { topResizeBar = DOM.createDiv(); bottomResizeBar = DOM.createDiv(); @@ -189,9 +187,11 @@ public class DateCellDayEvent extends FocusableHTML implements String escapedCaption = Util.escapeHTML(calendarEvent.getCaption()); String timeAsText = calendarEvent.getTimeAsText(); if (bigMode) { - innerHtml = "<span>" + timeAsText + "</span><br />" + escapedCaption; + innerHtml = "<span>" + timeAsText + "</span><br />" + + escapedCaption; } else { - innerHtml = "<span>" + timeAsText + "<span>:</span></span> " + escapedCaption; + innerHtml = "<span>" + timeAsText + "<span>:</span></span> " + + escapedCaption; } caption.setInnerHTML(innerHtml); eventContent.setInnerHTML(""); diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/DayToolbar.java b/client/src/com/vaadin/client/ui/calendar/schedule/DayToolbar.java index 6233e8111e..58b5fafa7f 100644 --- a/client/src/com/vaadin/client/ui/calendar/schedule/DayToolbar.java +++ b/client/src/com/vaadin/client/ui/calendar/schedule/DayToolbar.java @@ -72,8 +72,6 @@ public class DayToolbar extends HorizontalPanel implements ClickHandler { setCellWidth(nextLabel, MARGINRIGHT + "px"); setCellHorizontalAlignment(nextLabel, ALIGN_RIGHT); int cellw = width / (count - 2); - int remain = width % (count - 2); - int cellw2 = cellw + 1; if (cellw > 0) { int[] cellWidths = VCalendar .distributeSize(width, count - 2, 0); diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/MonthGrid.java b/client/src/com/vaadin/client/ui/calendar/schedule/MonthGrid.java index df9bc42d2a..3b1c774793 100644 --- a/client/src/com/vaadin/client/ui/calendar/schedule/MonthGrid.java +++ b/client/src/com/vaadin/client/ui/calendar/schedule/MonthGrid.java @@ -35,7 +35,6 @@ public class MonthGrid extends FocusableGrid implements KeyDownHandler { private SimpleDayCell selectionEnd; private final VCalendar calendar; private boolean rangeSelectDisabled; - private boolean disabled; private boolean enabled = true; private final HandlerRegistration keyDownHandler; diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java b/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java index cf8006ef66..00fc1ef3ea 100644 --- a/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java +++ b/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java @@ -83,7 +83,6 @@ public class SimpleDayCell extends FocusableFlowPanel implements private Widget clickedWidget; private HandlerRegistration bottomSpacerMouseDownHandler; private boolean scrollable = false; - private boolean eventCanceled; private MonthGrid monthGrid; private HandlerRegistration keyDownHandler; diff --git a/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java b/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java index f91ff9e2b9..8dec26cf90 100644 --- a/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java +++ b/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java @@ -37,6 +37,10 @@ import com.vaadin.ui.ComboBox; public class ComboBoxConnector extends AbstractFieldConnector implements Paintable, SimpleManagedLayout { + // oldSuggestionTextMatchTheOldSelection is used to detect when it's safe to + // update textbox text by a changed item caption. + private boolean oldSuggestionTextMatchTheOldSelection; + /* * (non-Javadoc) * @@ -117,7 +121,10 @@ public class ComboBoxConnector extends AbstractFieldConnector implements boolean suggestionsChanged = !getWidget().initDone || !newSuggestions.equals(getWidget().currentSuggestions); + oldSuggestionTextMatchTheOldSelection = false; + if (suggestionsChanged) { + oldSuggestionTextMatchTheOldSelection = isWidgetsCurrentSelectionTextInTextBox(); getWidget().currentSuggestions.clear(); if (!getWidget().waitingForFilteringResponse) { @@ -212,29 +219,38 @@ public class ComboBoxConnector extends AbstractFieldConnector implements // some item selected for (FilterSelectSuggestion suggestion : getWidget().currentSuggestions) { String suggestionKey = suggestion.getOptionKey(); - if (suggestionKey.equals(selectedKey)) { - if (!getWidget().waitingForFilteringResponse - || getWidget().popupOpenerClicked) { - if (!suggestionKey.equals(getWidget().selectedOptionKey) - || suggestion.getReplacementString().equals( - getWidget().tb.getText())) { - // Update text field if we've got a new - // selection - // Also update if we've got the same text to - // retain old text selection behavior - getWidget().setPromptingOff( - suggestion.getReplacementString()); - getWidget().selectedOptionKey = suggestionKey; - } + if (!suggestionKey.equals(selectedKey)) { + continue; + } + if (!getWidget().waitingForFilteringResponse + || getWidget().popupOpenerClicked) { + if (!suggestionKey.equals(getWidget().selectedOptionKey) + || suggestion.getReplacementString().equals( + getWidget().tb.getText()) + || oldSuggestionTextMatchTheOldSelection) { + // Update text field if we've got a new + // selection + // Also update if we've got the same text to + // retain old text selection behavior + // OR if selected item caption is changed. + getWidget().setPromptingOff( + suggestion.getReplacementString()); + getWidget().selectedOptionKey = suggestionKey; } - getWidget().currentSuggestion = suggestion; - getWidget().setSelectedItemIcon(suggestion.getIconUri()); - // only a single item can be selected - break; } + getWidget().currentSuggestion = suggestion; + getWidget().setSelectedItemIcon(suggestion.getIconUri()); + // only a single item can be selected + break; } } + private boolean isWidgetsCurrentSelectionTextInTextBox() { + return getWidget().currentSuggestion != null + && getWidget().currentSuggestion.getReplacementString().equals( + getWidget().tb.getText()); + } + private void resetSelection() { if (!getWidget().waitingForFilteringResponse || getWidget().popupOpenerClicked) { diff --git a/client/src/com/vaadin/client/ui/dd/VIsOverId.java b/client/src/com/vaadin/client/ui/dd/VIsOverId.java index f8083f8b60..7e2f596a20 100644 --- a/client/src/com/vaadin/client/ui/dd/VIsOverId.java +++ b/client/src/com/vaadin/client/ui/dd/VIsOverId.java @@ -19,7 +19,6 @@ package com.vaadin.client.ui.dd; import com.vaadin.client.ComponentConnector; -import com.vaadin.client.ConnectorMap; import com.vaadin.client.UIDL; import com.vaadin.shared.ui.dd.AcceptCriterion; import com.vaadin.ui.AbstractSelect; @@ -36,8 +35,6 @@ final public class VIsOverId extends VAcceptCriterion { .getCurrentDropHandler(); ComponentConnector dropHandlerConnector = currentDropHandler .getConnector(); - ConnectorMap paintableMap = ConnectorMap.get(currentDropHandler - .getApplicationConnection()); String pid2 = dropHandlerConnector.getConnectorId(); if (pid2.equals(pid)) { diff --git a/client/src/com/vaadin/client/ui/dd/VItemIdIs.java b/client/src/com/vaadin/client/ui/dd/VItemIdIs.java index 7d60eda4f9..b022f434f4 100644 --- a/client/src/com/vaadin/client/ui/dd/VItemIdIs.java +++ b/client/src/com/vaadin/client/ui/dd/VItemIdIs.java @@ -32,8 +32,6 @@ final public class VItemIdIs extends VAcceptCriterion { String pid = configuration.getStringAttribute("s"); ComponentConnector dragSource = drag.getTransferable() .getDragSource(); - VDropHandler currentDropHandler = VDragAndDropManager.get() - .getCurrentDropHandler(); String pid2 = dragSource.getConnectorId(); if (pid2.equals(pid)) { Object searchedId = drag.getTransferable().getData("itemId"); diff --git a/client/src/com/vaadin/client/ui/label/LabelConnector.java b/client/src/com/vaadin/client/ui/label/LabelConnector.java index 9639987e8d..6a04c91562 100644 --- a/client/src/com/vaadin/client/ui/label/LabelConnector.java +++ b/client/src/com/vaadin/client/ui/label/LabelConnector.java @@ -36,12 +36,6 @@ public class LabelConnector extends AbstractComponentConnector { } @Override - protected void init() { - super.init(); - getWidget().setConnection(getConnection()); - } - - @Override public void onStateChanged(StateChangeEvent stateChangeEvent) { super.onStateChanged(stateChangeEvent); boolean sinkOnloads = false; diff --git a/client/src/com/vaadin/client/ui/orderedlayout/Slot.java b/client/src/com/vaadin/client/ui/orderedlayout/Slot.java index 49b3661431..37a97f3399 100644 --- a/client/src/com/vaadin/client/ui/orderedlayout/Slot.java +++ b/client/src/com/vaadin/client/ui/orderedlayout/Slot.java @@ -19,9 +19,11 @@ package com.vaadin.client.ui.orderedlayout; import java.util.List; import com.google.gwt.aria.client.Roles; +import com.google.gwt.dom.client.Document; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.UIObject; import com.google.gwt.user.client.ui.Widget; @@ -456,6 +458,9 @@ public final class Slot extends SimplePanel { // Caption wrappers Widget widget = getWidget(); + final Element focusedElement = Util.getFocusedElement(); + // By default focus will not be lost + boolean focusLost = false; if (captionText != null || iconUrl != null || error != null || required) { if (caption == null) { caption = DOM.createDiv(); @@ -466,6 +471,10 @@ public final class Slot extends SimplePanel { orphan(widget); captionWrap.appendChild(widget.getElement()); adopt(widget); + + // Made changes to DOM. Focus can be lost if it was in the + // widget. + focusLost = widget.getElement().isOrHasChild(focusedElement); } } else if (caption != null) { orphan(widget); @@ -474,6 +483,9 @@ public final class Slot extends SimplePanel { captionWrap.removeFromParent(); caption = null; captionWrap = null; + + // Made changes to DOM. Focus can be lost if it was in the widget. + focusLost = widget.getElement().isOrHasChild(focusedElement); } // Caption text @@ -560,6 +572,45 @@ public final class Slot extends SimplePanel { setCaptionPosition(CaptionPosition.RIGHT); } } + + if (focusLost) { + // Find out what element is currently focused. + Element currentFocus = Util.getFocusedElement(); + if (currentFocus != null + && currentFocus.equals(Document.get().getBody())) { + // Focus has moved to BodyElement and should be moved back to + // original location. This happened because of adding or + // removing the captionWrap + focusedElement.focus(); + } else if (currentFocus != focusedElement) { + // Focus is either moved somewhere else on purpose or IE has + // lost it. Investigate further. + Timer focusTimer = new Timer() { + + @Override + public void run() { + if (Util.getFocusedElement() == null) { + // This should never become an infinite loop and + // even if it does it will be stopped once something + // is done with the browser. + schedule(25); + } else if (Util.getFocusedElement().equals( + Document.get().getBody())) { + // Focus found it's way to BodyElement. Now it can + // be restored + focusedElement.focus(); + } + } + }; + if (BrowserInfo.get().isIE8()) { + // IE8 can't fix the focus immediately. It will fail. + focusTimer.schedule(25); + } else { + // Newer IE versions can handle things immediately. + focusTimer.run(); + } + } + } } /** diff --git a/client/src/com/vaadin/client/ui/table/TableConnector.java b/client/src/com/vaadin/client/ui/table/TableConnector.java index eacd5bc77a..d2c700ab06 100644 --- a/client/src/com/vaadin/client/ui/table/TableConnector.java +++ b/client/src/com/vaadin/client/ui/table/TableConnector.java @@ -142,9 +142,6 @@ public class TableConnector extends AbstractHasComponentsConnector implements getWidget().updateSortingProperties(uidl); - boolean keyboardSelectionOverRowFetchInProgress = getWidget() - .selectSelectedRows(uidl); - getWidget().updateActionMap(uidl); getWidget().updateColumnProperties(uidl); @@ -216,6 +213,9 @@ public class TableConnector extends AbstractHasComponentsConnector implements } } + boolean keyboardSelectionOverRowFetchInProgress = getWidget() + .selectSelectedRows(uidl); + // If a row had an open context menu before the update, and after the // update there's a row with the same key as that row, restore the // context menu. See #8526. diff --git a/client/src/com/vaadin/client/ui/tree/TreeConnector.java b/client/src/com/vaadin/client/ui/tree/TreeConnector.java index 6f89137918..61207ffa53 100644 --- a/client/src/com/vaadin/client/ui/tree/TreeConnector.java +++ b/client/src/com/vaadin/client/ui/tree/TreeConnector.java @@ -18,6 +18,7 @@ package com.vaadin.client.ui.tree; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Set; import com.google.gwt.aria.client.Roles; import com.google.gwt.dom.client.Element; @@ -141,9 +142,24 @@ public class TreeConnector extends AbstractComponentConnector implements getWidget().lastSelection = getWidget().getNodeByKey( getWidget().lastSelection.key); } + if (getWidget().focusedNode != null) { - getWidget().setFocusedNode( - getWidget().getNodeByKey(getWidget().focusedNode.key)); + + Set<String> selectedIds = getWidget().selectedIds; + + // If the focused node is not between the selected nodes, we need to + // refresh the focused node to prevent an undesired scroll. #12618. + if (!selectedIds.isEmpty() + && !selectedIds.contains(getWidget().focusedNode.key)) { + String keySelectedId = selectedIds.iterator().next(); + + TreeNode nodeToSelect = getWidget().getNodeByKey(keySelectedId); + + getWidget().setFocusedNode(nodeToSelect); + } else { + getWidget().setFocusedNode( + getWidget().getNodeByKey(getWidget().focusedNode.key)); + } } if (getWidget().lastSelection == null diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index d0f3c8603f..17a23baad5 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -49,7 +49,6 @@ import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent; import com.vaadin.client.BrowserInfo; import com.vaadin.client.ComponentConnector; import com.vaadin.client.ConnectorHierarchyChangeEvent; -import com.vaadin.client.ConnectorMap; import com.vaadin.client.Focusable; import com.vaadin.client.Paintable; import com.vaadin.client.ServerConnector; @@ -192,7 +191,6 @@ public class UIConnector extends AbstractSingleComponentContainerConnector @Override public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) { - ConnectorMap paintableMap = ConnectorMap.get(getConnection()); getWidget().id = getConnectorId(); boolean firstPaint = getWidget().connection == null; getWidget().connection = client; diff --git a/client/src/com/vaadin/client/ui/upload/UploadConnector.java b/client/src/com/vaadin/client/ui/upload/UploadConnector.java index 937ff438ac..989a913adc 100644 --- a/client/src/com/vaadin/client/ui/upload/UploadConnector.java +++ b/client/src/com/vaadin/client/ui/upload/UploadConnector.java @@ -22,12 +22,22 @@ import com.vaadin.client.UIDL; import com.vaadin.client.ui.AbstractComponentConnector; import com.vaadin.client.ui.VUpload; import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.upload.UploadClientRpc; import com.vaadin.ui.Upload; @Connect(Upload.class) public class UploadConnector extends AbstractComponentConnector implements Paintable { + public UploadConnector() { + registerRpc(UploadClientRpc.class, new UploadClientRpc() { + @Override + public void submitUpload() { + getWidget().submit(); + } + }); + } + @Override public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { if (!isRealUpdate(uidl)) { @@ -37,10 +47,6 @@ public class UploadConnector extends AbstractComponentConnector implements getWidget().t.schedule(400); return; } - if (uidl.hasAttribute("forceSubmit")) { - getWidget().submit(); - return; - } getWidget().setImmediate(getState().immediate); getWidget().client = client; getWidget().paintableId = uidl.getId(); diff --git a/common.xml b/common.xml index a1c086c57a..a49c25c6be 100644 --- a/common.xml +++ b/common.xml @@ -139,6 +139,7 @@ <fileset dir="${src}"> <patternset> <include name="**/*.java" /> + <include name="**/*.properties" /> </patternset> </fileset> <fileset refid="common.files.for.all.jars" /> @@ -184,7 +185,7 @@ <property name="src" location="{$result.dir}/../src" /> <union id="jar.files"> - <fileset dir="${classes}" excludes="${classes.exclude}" erroronmissingdir="false" /> + <fileset dir="${classes}" excludes="${classes.exclude}" erroronmissingdir="false"/> <fileset dir="${src}" excludes="${jar.exclude}" erroronmissingdir="false" /> <fileset refid="common.files.for.all.jars" /> <union refid="extra.jar.includes" /> @@ -277,6 +278,9 @@ <classpath refid="classpath.compile.dependencies" /> <classpath refid="classpath.compile.custom" /> </javac> + <copy todir="${classes}"> + <fileset dir="${src}" includes="${extra.classes}"/> + </copy> </target> <target name="exec-buildhelper" depends="compile"> diff --git a/eclipse/Development Server (vaadin).launch b/eclipse/Development Server (vaadin).launch index 8f57c441ec..9505811c0b 100644 --- a/eclipse/Development Server (vaadin).launch +++ b/eclipse/Development Server (vaadin).launch @@ -6,6 +6,13 @@ <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listEntry value="1"/> </listAttribute> +<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> +<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" javaProject="vaadin" path="1" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=vaadin&amp;ivyXmlPath=uitest%2Fivy.xml&amp;confs=jetty-run" path="3" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="vaadin"/> </runtimeClasspathEntry> "/> +</listAttribute> +<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.vaadin.launcher.DevelopmentServerLauncher"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="vaadin"/> <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/> diff --git a/publish.xml b/publish.xml index d37087d8f9..2fafb68246 100644 --- a/publish.xml +++ b/publish.xml @@ -20,6 +20,9 @@ <property name="file.war" location="result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${version}.war" /> <property name="target" value="${nightly.tests.publish}/${vaadin.version.major}.${vaadin.version.minor}-${build.tag}.war" /> + <fail unless="ant-jsch.present" message="Please install ant-jsch.jar into ANT_HOME/lib" /> + <fail unless="jsch.present" message="Please install jsch.jar into ANT_HOME/lib" /> + <echo>Installing ${src} to ${target}</echo> <scp todir="${nightly.tests.publish}" file="${file.war}"> @@ -34,7 +37,7 @@ <antcontrib:foreach list="${modules.to.publish.to.maven}" target="publish.module.to.maven" param="module" /> </target> - <target name="publish.module.to.download.site"> + <target name="publish.module.to.download.site"> <fail unless="module" message="No module to publish defined" /> <ivy:resolve log="download-only" file="${module}/ivy.xml" /> <ivy:publish publishivy="false" settingsref="publish.settings" conf="*(public)" resolver="sftp-publish"> @@ -65,4 +68,31 @@ </artifact:mvn> </target> + <!-- Use this to publish to local Maven repo --> + <!-- If you have compiled a snapshot build with: --> + <!-- ant -Dvaadin.version=7.x.x.zzz package --> + <!-- Publish with: --> + <!-- ant -f publish.xml -Dvaadin.version=7.x.x.zzz local.maven.publish --> + <!-- Note that if the build is a snapshot build, it will be installed as --> + <!-- 7.x-SNAPSHOT. --> + <target name="local.maven.publish"> + <antcontrib:foreach list="${modules.to.publish.to.maven}" target="publish.module.to.local.maven" param="module" /> + </target> + + <target name="publish.module.to.local.maven"> + <fail unless="module" message="No module to publish defined" /> + + <property name="jar.file" location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}.jar" /> + <property name="javadoc.file" location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}-javadoc.jar" /> + <property name="sources.file" location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}-sources.jar" /> + <property name="pom.file" location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}.pom" /> + + <artifact:mvn failonerror="true"> + <arg value="install:install-file" /> + <sysproperty key="file" value="${jar.file}" /> + <sysproperty key="pomFile" value="${pom.file}" /> + <sysproperty key="javadoc" value="${javadoc.file}" /> + <sysproperty key="sources" value="${sources.file}" /> + </artifact:mvn> + </target> </project> diff --git a/push/build.xml b/push/build.xml index abeec2a8b0..0db99e815c 100644 --- a/push/build.xml +++ b/push/build.xml @@ -16,7 +16,7 @@ <property name="vaadinPush.debug.js" location="${result.dir}/js/VAADIN/vaadinPush.debug.js" /> <!-- Keep the version number in sync with ivy.xml, server/src/com/vaadin/server/Constants.java --> - <property name="atmosphere.runtime.version" value="1.0.18.vaadin1" /> + <property name="atmosphere.runtime.version" value="2.0.3.vaadin1" /> <property name="jquery.version" value="1.9.0" /> <path id="classpath.compile.custom" /> diff --git a/push/ivy.xml b/push/ivy.xml index 2be47512fe..b28c5c69d9 100644 --- a/push/ivy.xml +++ b/push/ivy.xml @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ivy-module [ <!-- Keep the version number in sync with build.xml --> - <!ENTITY atmosphere.runtime.version "1.0.18.vaadin1"> + <!ENTITY atmosphere.runtime.version "2.0.3.vaadin1"> - <!ENTITY atmosphere.js.version "2.0.3.vaadin2"> + <!ENTITY atmosphere.js.version "2.0.8.vaadin1"> ]> <ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" diff --git a/server/src/com/vaadin/data/Buffered.java b/server/src/com/vaadin/data/Buffered.java index 0d6722f71f..c4c79ae13f 100644 --- a/server/src/com/vaadin/data/Buffered.java +++ b/server/src/com/vaadin/data/Buffered.java @@ -23,29 +23,20 @@ import com.vaadin.data.Validator.InvalidValueException; /** * <p> * Defines the interface to commit and discard changes to an object, supporting - * read-through and write-through modes. - * </p> + * buffering. * * <p> - * <i>Read-through mode</i> means that the value read from the buffered object - * is constantly up to date with the data source. <i>Write-through</i> mode - * means that all changes to the object are immediately updated to the data - * source. - * </p> + * In <i>buffered</i> mode the initial value is read from the data source and + * then buffered. Any subsequential writes or reads will be done on the buffered + * value. Calling {@link #commit()} will write the buffered value to the data + * source while calling {@link #discard()} while discard the buffered value and + * re-read the value from the data source. * * <p> - * Since these modes are independent, their combinations may result in some - * behaviour that may sound surprising. - * </p> - * - * <p> - * For example, if a <code>Buffered</code> object is in read-through mode but - * not in write-through mode, the result is an object whose value is updated - * directly from the data source only if it's not locally modified. If the value - * is locally modified, retrieving the value from the object would result in a - * value that is different than the one stored in the data source, even though - * the object is in read-through mode. - * </p> + * In <i>non-buffered</i> mode the value is always read directly from the data + * source. Any write is done directly to the data source with no buffering in + * between. Reads are also done directly from the data source. Calling + * {@link #commit()} or {@link #discard()} in this mode is efficiently a no-op. * * @author Vaadin Ltd. * @since 3.0 @@ -77,25 +68,15 @@ public interface Buffered extends Serializable { public void discard() throws SourceException; /** - * Sets the object's buffered mode to the specified status. + * Sets the buffered mode to the specified status. * <p> - * When the object is in buffered mode, an internal buffer will be used to - * store changes until {@link #commit()} is called. Calling - * {@link #discard()} will revert the internal buffer to the value of the - * data source. - * </p> + * When in buffered mode, an internal buffer will be used to store changes + * until {@link #commit()} is called. Calling {@link #discard()} will revert + * the internal buffer to the value of the data source. * <p> - * This is an easier way to use {@link #setReadThrough(boolean)} and - * {@link #setWriteThrough(boolean)} and not as error prone. Changing - * buffered mode will change both the read through and write through state - * of the object. - * </p> - * <p> - * Mixing calls to {@link #setBuffered(boolean)}/{@link #isBuffered()} and - * {@link #setReadThrough(boolean)}/{@link #isReadThrough()} or - * {@link #setWriteThrough(boolean)}/{@link #isWriteThrough()} is generally - * a bad idea. - * </p> + * When in non-buffered mode both read and write operations will be done + * directly on the data source. In this mode the {@link #commit()} and + * {@link #discard()} methods serve no purpose. * * @param buffered * true if buffered mode should be turned on, false otherwise @@ -104,10 +85,7 @@ public interface Buffered extends Serializable { public void setBuffered(boolean buffered); /** - * Checks the buffered mode of this Object. - * <p> - * This method only returns true if both read and write buffering is used. - * </p> + * Checks the buffered mode * * @return true if buffered mode is on, false otherwise * @since 7.0 diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java index 23f2da53ce..7edcc9719c 100644 --- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java @@ -23,7 +23,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; -import java.util.logging.Logger; import com.vaadin.data.Item; import com.vaadin.data.Property; @@ -55,9 +54,6 @@ import com.vaadin.util.ReflectTools; */ public class FieldGroup implements Serializable { - private static final Logger logger = Logger.getLogger(FieldGroup.class - .getName()); - private Item itemDataSource; private boolean buffered = true; @@ -1013,9 +1009,7 @@ public class FieldGroup implements Serializable { */ public Field<?> buildAndBind(String caption, Object propertyId) throws BindException { - Class<?> type = getPropertyType(propertyId); return buildAndBind(caption, propertyId, Field.class); - } /** diff --git a/server/src/com/vaadin/data/util/filter/Between.java b/server/src/com/vaadin/data/util/filter/Between.java index 8209f7b0a2..a76821981a 100644 --- a/server/src/com/vaadin/data/util/filter/Between.java +++ b/server/src/com/vaadin/data/util/filter/Between.java @@ -67,6 +67,10 @@ public class Between implements Filter { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } + // Only objects of the same class can be equal if (!getClass().equals(obj.getClass())) { return false; diff --git a/server/src/com/vaadin/data/util/filter/Compare.java b/server/src/com/vaadin/data/util/filter/Compare.java index f9f19c6602..ac167673bd 100644 --- a/server/src/com/vaadin/data/util/filter/Compare.java +++ b/server/src/com/vaadin/data/util/filter/Compare.java @@ -307,6 +307,9 @@ public abstract class Compare implements Filter { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } // Only objects of the same class can be equal if (!getClass().equals(obj.getClass())) { diff --git a/server/src/com/vaadin/data/util/filter/IsNull.java b/server/src/com/vaadin/data/util/filter/IsNull.java index 5c5bdfc0b1..6907a016a1 100644 --- a/server/src/com/vaadin/data/util/filter/IsNull.java +++ b/server/src/com/vaadin/data/util/filter/IsNull.java @@ -62,6 +62,10 @@ public final class IsNull implements Filter { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } + // Only objects of the same class can be equal if (!getClass().equals(obj.getClass())) { return false; diff --git a/server/src/com/vaadin/data/util/filter/Like.java b/server/src/com/vaadin/data/util/filter/Like.java index 4c15564105..dc2e18363a 100644 --- a/server/src/com/vaadin/data/util/filter/Like.java +++ b/server/src/com/vaadin/data/util/filter/Like.java @@ -84,6 +84,10 @@ public class Like implements Filter { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } + // Only objects of the same class can be equal if (!getClass().equals(obj.getClass())) { return false; diff --git a/server/src/com/vaadin/data/util/filter/SimpleStringFilter.java b/server/src/com/vaadin/data/util/filter/SimpleStringFilter.java index bc58999445..a214e69846 100644 --- a/server/src/com/vaadin/data/util/filter/SimpleStringFilter.java +++ b/server/src/com/vaadin/data/util/filter/SimpleStringFilter.java @@ -82,6 +82,9 @@ public final class SimpleStringFilter implements Filter { @Override public boolean equals(Object obj) { + if (obj == null) { + return false; + } // Only ones of the objects of the same class can be equal if (!(obj instanceof SimpleStringFilter)) { diff --git a/server/src/com/vaadin/event/EventRouter.java b/server/src/com/vaadin/event/EventRouter.java index 73bfa33881..fdc543143b 100644 --- a/server/src/com/vaadin/event/EventRouter.java +++ b/server/src/com/vaadin/event/EventRouter.java @@ -23,6 +23,10 @@ import java.util.EventObject; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; +import java.util.logging.Logger; + +import com.vaadin.server.ErrorEvent; +import com.vaadin.server.ErrorHandler; /** * <code>EventRouter</code> class implementing the inheritable event listening @@ -154,6 +158,25 @@ public class EventRouter implements MethodEventSource { * the Event to be sent to all listeners. */ public void fireEvent(EventObject event) { + fireEvent(event, null); + } + + /** + * Sends an event to all registered listeners. The listeners will decide if + * the activation method should be called or not. + * <p> + * If an error handler is set, the processing of other listeners will + * continue after the error handler method call unless the error handler + * itself throws an exception. + * + * @param event + * the Event to be sent to all listeners. + * @param errorHandler + * error handler to use to handle any exceptions thrown by + * listeners or null to let the exception propagate to the + * caller, preventing further listener calls + */ + public void fireEvent(EventObject event, ErrorHandler errorHandler) { // It is not necessary to send any events if there are no listeners if (listenerList != null) { @@ -164,7 +187,16 @@ public class EventRouter implements MethodEventSource { // will filter out unwanted events. final Object[] listeners = listenerList.toArray(); for (int i = 0; i < listeners.length; i++) { - ((ListenerMethod) listeners[i]).receiveEvent(event); + ListenerMethod listenerMethod = (ListenerMethod) listeners[i]; + if (null != errorHandler) { + try { + listenerMethod.receiveEvent(event); + } catch (Exception e) { + errorHandler.error(new ErrorEvent(e)); + } + } else { + listenerMethod.receiveEvent(event); + } } } @@ -208,4 +240,9 @@ public class EventRouter implements MethodEventSource { } return listeners; } + + private Logger getLogger() { + return Logger.getLogger(EventRouter.class.getName()); + } + } diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java index b0841da314..a39c39fa72 100644 --- a/server/src/com/vaadin/server/Constants.java +++ b/server/src/com/vaadin/server/Constants.java @@ -67,7 +67,7 @@ public interface Constants { // Keep the version number in sync with push/build.xml and other locations // listed in that file - static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "1.0.18.vaadin1"; + static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.0.3.vaadin1"; static final String INVALID_ATMOSPHERE_VERSION_WARNING = "\n" + "=================================================================\n" diff --git a/server/src/com/vaadin/server/JsonCodec.java b/server/src/com/vaadin/server/JsonCodec.java index d533ed99f3..129307e5c1 100644 --- a/server/src/com/vaadin/server/JsonCodec.java +++ b/server/src/com/vaadin/server/JsonCodec.java @@ -31,6 +31,7 @@ import java.lang.reflect.WildcardType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -45,6 +46,8 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import com.vaadin.server.communication.DateSerializer; +import com.vaadin.server.communication.JSONSerializer; import com.vaadin.shared.Connector; import com.vaadin.shared.JsonConstants; import com.vaadin.shared.communication.UidlValue; @@ -176,6 +179,11 @@ public class JsonCodec implements Serializable { */ private static Map<String, Class<?>> transportTypeToType = new HashMap<String, Class<?>>(); + private static Map<Class<?>, JSONSerializer<?>> customSerializers = new HashMap<Class<?>, JSONSerializer<?>>(); + static { + customSerializers.put(Date.class, new DateSerializer()); + } + static { registerType(String.class, JsonConstants.VTYPE_STRING); registerType(Connector.class, JsonConstants.VTYPE_CONNECTOR); @@ -283,6 +291,9 @@ public class JsonCodec implements Serializable { Class<?> classForType = getClassForType(targetType); return decodeEnum(classForType.asSubclass(Enum.class), (String) value); + } else if (customSerializers.containsKey(getClassForType(targetType))) { + return customSerializers.get(getClassForType(targetType)) + .deserialize(targetType, value, connectorTracker); } else { return decodeObject(targetType, (JSONObject) value, connectorTracker); @@ -676,6 +687,10 @@ public class JsonCodec implements Serializable { return encodeEnum((Enum<?>) value, connectorTracker); } else if (value instanceof JSONArray || value instanceof JSONObject) { return new EncodeResult(value); + } else if (customSerializers.containsKey(value.getClass())) { + JSONSerializer serializer = customSerializers.get(value.getClass()); + return new EncodeResult(serializer.serialize(value, + connectorTracker)); } else if (valueType instanceof Class<?>) { // Any object that we do not know how to encode we encode by looping // through fields diff --git a/server/src/com/vaadin/server/LegacyCommunicationManager.java b/server/src/com/vaadin/server/LegacyCommunicationManager.java index ad662cf6df..8d61968b47 100644 --- a/server/src/com/vaadin/server/LegacyCommunicationManager.java +++ b/server/src/com/vaadin/server/LegacyCommunicationManager.java @@ -316,8 +316,6 @@ public class LegacyCommunicationManager implements Serializable { private final HashMap<Class<? extends ClientConnector>, Integer> typeToKey = new HashMap<Class<? extends ClientConnector>, Integer>(); private int nextTypeKey = 0; - private BootstrapHandler bootstrapHandler; - /** * @deprecated As of 7.1. Will be removed in the future. */ diff --git a/server/src/com/vaadin/server/VaadinPortlet.java b/server/src/com/vaadin/server/VaadinPortlet.java index a41f301219..6cf30e85e9 100644 --- a/server/src/com/vaadin/server/VaadinPortlet.java +++ b/server/src/com/vaadin/server/VaadinPortlet.java @@ -365,7 +365,6 @@ public class VaadinPortlet extends GenericPortlet implements Constants, if (request instanceof RenderRequest) { return RequestType.RENDER; } else if (request instanceof ResourceRequest) { - ResourceRequest resourceRequest = (ResourceRequest) request; if (ServletPortletHelper.isUIDLRequest(vaadinRequest)) { return RequestType.UIDL; } else if (PortletUIInitHandler.isUIInitRequest(vaadinRequest)) { diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index aff0124d16..b457436b8f 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -420,6 +420,9 @@ public abstract class VaadinService implements Serializable { /** * Adds a listener that gets notified when a Vaadin service session that has * been initialized for this service is destroyed. + * <p> + * The session being destroyed is locked and its UIs have been removed when + * the listeners are called. * * @see #addSessionInitListener(SessionInitListener) * @@ -461,8 +464,11 @@ public abstract class VaadinService implements Serializable { } }); } + // for now, use the session error handler; in the future, could + // have an API for using some other handler for session init and + // destroy listeners eventRouter.fireEvent(new SessionDestroyEvent( - VaadinService.this, session)); + VaadinService.this, session), session.getErrorHandler()); } }); } @@ -776,7 +782,12 @@ public abstract class VaadinService implements Serializable { private void onVaadinSessionStarted(VaadinRequest request, VaadinSession session) throws ServiceException { - eventRouter.fireEvent(new SessionInitEvent(this, session, request)); + // for now, use the session error handler; in the future, could have an + // API for using some other handler for session init and destroy + // listeners + + eventRouter.fireEvent(new SessionInitEvent(this, session, request), + session.getErrorHandler()); ServletPortletHelper.checkUiProviders(session, this); } diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java index f34721944a..265d18b859 100644 --- a/server/src/com/vaadin/server/VaadinSession.java +++ b/server/src/com/vaadin/server/VaadinSession.java @@ -22,12 +22,15 @@ import java.io.Serializable; import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; +import java.util.Enumeration; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Queue; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; @@ -423,6 +426,32 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { } /** + * Retrieves all {@link VaadinSession}s which are stored in the given HTTP + * session + * + * @since 7.2 + * @param httpSession + * the HTTP session + * @return the found VaadinSessions + */ + public static Collection<VaadinSession> getAllSessions( + HttpSession httpSession) { + Set<VaadinSession> sessions = new HashSet<VaadinSession>(); + Enumeration<String> attributeNames = httpSession.getAttributeNames(); + + while (attributeNames.hasMoreElements()) { + String attributeName = attributeNames.nextElement(); + if (attributeName.startsWith(VaadinSession.class.getName() + ".")) { + Object value = httpSession.getAttribute(attributeName); + if (value instanceof VaadinSession) { + sessions.add((VaadinSession) value); + } + } + } + return sessions; + } + + /** * Removes this VaadinSession from the HTTP session. * * @param service diff --git a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java index b9d4955b12..56dd576403 100644 --- a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java +++ b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java @@ -22,22 +22,16 @@ import java.io.Serializable; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; import org.atmosphere.cpr.AtmosphereResource; import org.atmosphere.cpr.AtmosphereResource.TRANSPORT; -import org.json.JSONException; import com.vaadin.shared.communication.PushConstants; import com.vaadin.ui.UI; /** - * {@link PushConnection} implementation using the Atmosphere push support that - * is by default included in Vaadin. + * A {@link PushConnection} implementation using the Atmosphere push support + * that is by default included in Vaadin. * * @author Vaadin Ltd * @since 7.1 @@ -92,55 +86,84 @@ public class AtmospherePushConnection implements PushConnection { } } + protected enum State { + /** + * Not connected. Trying to push will set the connection state to + * PUSH_PENDING or RESPONSE_PENDING and defer sending the message until + * a connection is established. + */ + DISCONNECTED, + + /** + * Not connected. An asynchronous push is pending the opening of the + * connection. + */ + PUSH_PENDING, + + /** + * Not connected. A response to a client request is pending the opening + * of the connection. + */ + RESPONSE_PENDING, + + /** + * Connected. Messages can be sent through the connection. + */ + CONNECTED; + } + + private State state = State.DISCONNECTED; private UI ui; private AtmosphereResource resource; - private Future<String> outgoingMessage; private FragmentedMessage incomingMessage; - public AtmospherePushConnection(UI ui, AtmosphereResource resource) { + public AtmospherePushConnection(UI ui) { this.ui = ui; - this.resource = resource; } @Override public void push() { - assert isConnected(); - try { - push(true); - } catch (IOException e) { - // TODO Error handling - throw new RuntimeException("Push failed", e); - } + push(true); } /** - * Pushes pending state changes and client RPC calls to the client. + * Pushes pending state changes and client RPC calls to the client. If + * {@code isConnected()} is false, defers the push until a connection is + * established. * * @param async * True if this push asynchronously originates from the server, * false if it is a response to a client request. - * @throws IOException */ - protected void push(boolean async) throws IOException { - Writer writer = new StringWriter(); - try { - new UidlWriter().write(getUI(), writer, false, async); - } catch (JSONException e) { - throw new IOException("Error writing UIDL", e); + public void push(boolean async) { + if (!isConnected()) { + if (async && state != State.RESPONSE_PENDING) { + state = State.PUSH_PENDING; + } else { + state = State.RESPONSE_PENDING; + } + } else { + try { + Writer writer = new StringWriter(); + new UidlWriter().write(getUI(), writer, false, async); + sendMessage("for(;;);[{" + writer.toString() + "}]"); + } catch (Exception e) { + throw new RuntimeException("Push failed", e); + } } - sendMessage("for(;;);[{" + writer.toString() + "}]"); } /** - * Sends the given message to the current client. + * Sends the given message to the current client. Cannot be called if + * {@isConnected()} is false. * * @param message * The message to send */ void sendMessage(String message) { + assert (isConnected()); // "Broadcast" the changes to the single client only - outgoingMessage = getResource().getBroadcaster().broadcast(message, - getResource()); + getResource().getBroadcaster().broadcast(message, getResource()); } /** @@ -157,7 +180,7 @@ public class AtmospherePushConnection implements PushConnection { */ protected Reader receiveMessage(Reader reader) throws IOException { - if (resource.transport() != TRANSPORT.WEBSOCKET) { + if (resource == null || resource.transport() != TRANSPORT.WEBSOCKET) { return reader; } @@ -179,9 +202,37 @@ public class AtmospherePushConnection implements PushConnection { @Override public boolean isConnected() { - return resource != null - && resource.getBroadcaster().getAtmosphereResources() - .contains(resource); + assert (state == State.CONNECTED) ^ (resource == null); + return state == State.CONNECTED; + } + + /** + * Associates this {@code AtmospherePushConnection} with the given + * {@AtmosphereResource} representing an established + * push connection. If already connected, calls {@link #disconnect()} first. + * If there is a deferred push, carries it out via the new connection. + * + * @since 7.2 + */ + public void connect(AtmosphereResource resource) { + + assert resource != null; + assert resource != this.resource; + + if (isConnected()) { + disconnect(); + } + + this.resource = resource; + State oldState = state; + state = State.CONNECTED; + + if (oldState == State.PUSH_PENDING + || oldState == State.RESPONSE_PENDING) { + // Sending a "response" message (async=false) also takes care of a + // pending push, but not vice versa + push(oldState == State.PUSH_PENDING); + } } /** @@ -202,33 +253,8 @@ public class AtmospherePushConnection implements PushConnection { @Override public void disconnect() { assert isConnected(); - - if (outgoingMessage != null) { - // Wait for the last message to be sent before closing the - // connection (assumes that futures are completed in order) - try { - outgoingMessage.get(1000, TimeUnit.MILLISECONDS); - } catch (TimeoutException e) { - getLogger() - .log(Level.INFO, - "Timeout waiting for messages to be sent to client before disconnect"); - } catch (Exception e) { - getLogger() - .log(Level.INFO, - "Error waiting for messages to be sent to client before disconnect"); - } - outgoingMessage = null; - } - resource.resume(); resource = null; - } - - /** - * @since - * @return - */ - private static Logger getLogger() { - return Logger.getLogger(AtmospherePushConnection.class.getName()); + state = State.DISCONNECTED; } } diff --git a/server/src/com/vaadin/server/communication/DateSerializer.java b/server/src/com/vaadin/server/communication/DateSerializer.java new file mode 100644 index 0000000000..9179eb922b --- /dev/null +++ b/server/src/com/vaadin/server/communication/DateSerializer.java @@ -0,0 +1,42 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.server.communication; + +import java.lang.reflect.Type; +import java.util.Date; + +import com.vaadin.ui.ConnectorTracker; + +/** + * Server side serializer/deserializer for java.util.Date + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class DateSerializer implements JSONSerializer<Date> { + + @Override + public Date deserialize(Type type, Object jsonValue, + ConnectorTracker connectorTracker) { + return new Date(Long.valueOf(String.valueOf(jsonValue))); + } + + @Override + public Object serialize(Date value, ConnectorTracker connectorTracker) { + return value.getTime(); + } + +} diff --git a/server/src/com/vaadin/server/communication/JSONSerializer.java b/server/src/com/vaadin/server/communication/JSONSerializer.java new file mode 100644 index 0000000000..fe609c70b6 --- /dev/null +++ b/server/src/com/vaadin/server/communication/JSONSerializer.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.server.communication; + +import java.lang.reflect.Type; + +import com.vaadin.ui.ConnectorTracker; + +/** + * Implementors of this interface knows how to serialize an Object of a given + * type to JSON and how to deserialize the JSON back into an object. + * <p> + * The {@link #serialize(Object, ConnectorTracker)} and + * {@link #deserialize(Type, Object, ConnectorTracker)} methods must be + * symmetric so they can be chained and produce the original result (or an equal + * result). + * <p> + * Each {@link JSONSerializer} implementation can handle an object of a single + * type. + * <p> + * This is the server side interface, see + * com.vaadin.client.communication.JSONSerializer for the client side interface. + * + * @since 7.2 + * @author Vaadin Ltd + */ +public interface JSONSerializer<T> { + /** + * Creates and deserializes an object received from the client. Must be + * compatible with {@link #serialize(Object, ConnectorTracker)} and also + * with the client side com.vaadin.client.communication.JSONSerializer. + * <p> + * The json parameter is of type Object as org.json JSON classes have no + * other common super class + * + * @param type + * The expected return type + * @param jsonValue + * the value from the JSON + * @param connectorTracker + * the connector tracker instance for the UI + * @return A deserialized object + */ + T deserialize(Type type, Object jsonValue, ConnectorTracker connectorTracker); + + /** + * Serialize the given object into JSON. Must be compatible with + * {@link #deserialize(Object, connectorTracker)} and the client side + * com.vaadin.client.communication.JSONSerializer + * + * @param value + * The object to serialize + * @param connectorTracker + * The connector tracker instance for the UI + * @return A JSON serialized version of the object + */ + Object serialize(T value, ConnectorTracker connectorTracker); + +} diff --git a/server/src/com/vaadin/server/communication/PushConnection.java b/server/src/com/vaadin/server/communication/PushConnection.java index 7f78d1d48e..cab3c94824 100644 --- a/server/src/com/vaadin/server/communication/PushConnection.java +++ b/server/src/com/vaadin/server/communication/PushConnection.java @@ -20,7 +20,12 @@ import com.vaadin.ui.UI; /** * Represents a bidirectional ("push") connection between a single UI and its - * client-side. + * client-side. A single {@code PushConnection} instance is bound to a UI as + * long as push is enabled in that UI, even if the actual connection is + * momentarily dropped either due to a network failure or as a normal part of + * the transport mechanism. + * <p> + * This interface is an internal API, only meant to be used by the framework. * * @author Vaadin Ltd * @since 7.1 @@ -28,9 +33,10 @@ import com.vaadin.ui.UI; public interface PushConnection { /** - * Pushes pending state changes and client RPC calls to the client. Cannot - * be called if {@link #isConnected()} is false. It is NOT safe to invoke - * this method if not holding the session lock. + * Pushes pending state changes and client RPC calls to the client. Can be + * called even if {@link #isConnected()} is false; the push will be deferred + * until a connection is available. It is NOT safe to invoke this method if + * not holding the session lock. * <p> * This is internal API; please use {@link UI#push()} instead. */ diff --git a/server/src/com/vaadin/server/communication/PushHandler.java b/server/src/com/vaadin/server/communication/PushHandler.java index 09428e47a9..99aff3780f 100644 --- a/server/src/com/vaadin/server/communication/PushHandler.java +++ b/server/src/com/vaadin/server/communication/PushHandler.java @@ -19,7 +19,6 @@ package com.vaadin.server.communication; import java.io.IOException; import java.io.Reader; import java.io.Writer; -import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; @@ -43,7 +42,6 @@ import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinServletRequest; import com.vaadin.server.VaadinServletService; import com.vaadin.server.VaadinSession; -import com.vaadin.server.WebBrowser; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.communication.PushMode; import com.vaadin.ui.UI; @@ -75,8 +73,8 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter @Override public void run(AtmosphereResource resource, UI ui) throws IOException { getLogger().log(Level.FINER, - "New push connection with transport {0}", - resource.transport()); + "New push connection for resource {0} with transport {1}", + new Object[] { resource.uuid(), resource.transport() }); resource.addEventListener(PushHandler.this); @@ -84,14 +82,6 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter VaadinSession session = ui.getSession(); if (resource.transport() == TRANSPORT.STREAMING) { - // IE8 requires a longer padding to work properly if the - // initial message is small (#11573). Chrome does not work - // without the original padding... - WebBrowser browser = session.getBrowser(); - if (browser.isIE() && browser.getBrowserMajorVersion() == 8) { - resource.padding(LONG_PADDING); - } - // Must ensure that the streaming response contains // "Connection: close", otherwise iOS 6 will wait for the // response to this request before sending another request to @@ -115,10 +105,9 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter resource.suspend(); - AtmospherePushConnection connection = new AtmospherePushConnection( - ui, resource); - - ui.setPushConnection(connection); + AtmospherePushConnection connection = getConnectionForUI(ui); + assert (connection != null); + connection.connect(resource); } }; @@ -182,11 +171,11 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter @Override public void run(AtmosphereResource resource, UI ui) throws IOException { PushMode pushMode = ui.getPushConfiguration().getPushMode(); - AtmospherePushConnection pushConnection = getConnectionForUI(ui); + AtmospherePushConnection connection = getConnectionForUI(ui); String id = resource.uuid(); - if (pushConnection == null) { + if (connection == null) { getLogger() .log(Level.WARNING, "Could not find push connection to close: {0} with transport {1}", @@ -209,19 +198,11 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter "Connection unexpectedly closed for resource {0} with transport {1}", new Object[] { id, resource.transport() }); } - ui.setPushConnection(null); + connection.disconnect(); } } }; - private static final String LONG_PADDING; - - static { - char[] array = new char[4096]; - Arrays.fill(array, '-'); - LONG_PADDING = String.copyValueOf(array); - - } private VaadinServletService service; public PushHandler(VaadinServletService service) { @@ -351,10 +332,10 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter private static AtmospherePushConnection getConnectionForUI(UI ui) { PushConnection pushConnection = ui.getPushConnection(); if (pushConnection instanceof AtmospherePushConnection) { - assert pushConnection.isConnected(); return (AtmospherePushConnection) pushConnection; + } else { + return null; } - return null; } @Override @@ -391,7 +372,7 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter break; case JSONP: case LONG_POLLING: - resource.resume(); + disconnect(event); break; default: getLogger().log(Level.SEVERE, "Unknown transport {0}", @@ -415,13 +396,6 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter } @Override - public void onResume(AtmosphereResourceEvent event) { - // Log event on trace level - super.onResume(event); - disconnect(event); - } - - @Override public void destroy() { } @@ -444,8 +418,8 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter */ private static void sendRefreshAndDisconnect(AtmosphereResource resource) throws IOException { - AtmospherePushConnection connection = new AtmospherePushConnection( - null, resource); + AtmospherePushConnection connection = new AtmospherePushConnection(null); + connection.connect(resource); try { connection.sendMessage(VaadinService .createCriticalNotificationJSON(null, null, null, null)); diff --git a/server/src/com/vaadin/server/communication/PushRequestHandler.java b/server/src/com/vaadin/server/communication/PushRequestHandler.java index 74595322a0..f3869a76f8 100644 --- a/server/src/com/vaadin/server/communication/PushRequestHandler.java +++ b/server/src/com/vaadin/server/communication/PushRequestHandler.java @@ -18,6 +18,7 @@ package com.vaadin.server.communication; import java.io.IOException; +import javax.servlet.ServletConfig; import javax.servlet.ServletException; import org.atmosphere.client.TrackMessageSizeInterceptor; @@ -58,11 +59,22 @@ public class PushRequestHandler implements RequestHandler, public PushRequestHandler(VaadinServletService service) throws ServiceException { + final ServletConfig config = service.getServlet().getServletConfig(); + atmosphere = new AtmosphereFramework() { @Override protected void analytics() { // Overridden to disable version number check } + + @Override + public AtmosphereFramework addInitParameter(String name, + String value) { + if (config.getInitParameter(name) == null) { + super.addInitParameter(name, value); + } + return this; + } }; service.addServiceDestroyListener(new ServiceDestroyListener() { @@ -93,7 +105,7 @@ public class PushRequestHandler implements RequestHandler, "false"); try { - atmosphere.init(service.getServlet().getServletConfig()); + atmosphere.init(config); // Ensure the client-side knows how to split the message stream // into individual messages when using certain transports diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java index 432a9ea893..ce9cec5e2a 100644 --- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java +++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java @@ -68,7 +68,7 @@ public class ServerRpcHandler implements Serializable { * @since 7.2 * @author Vaadin Ltd */ - public static class RpcRequest { + public static class RpcRequest implements Serializable { private final String csrfToken; private final JSONArray invocations; @@ -439,7 +439,7 @@ public class ServerRpcHandler implements Serializable { "Ignoring RPC call to " + interfaceName + "." + methodName + " in connector " + connector.getClass().getName() + "(" + connectorId - + ") as no RPC implementation is regsitered"); + + ") as no RPC implementation is registered"); return null; } diff --git a/server/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java b/server/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java index cc04e50b3c..3ad76794de 100644 --- a/server/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java +++ b/server/src/com/vaadin/server/widgetsetutils/ClassPathExplorer.java @@ -32,8 +32,6 @@ import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Utility class to collect widgetset related information from classpath. @@ -111,6 +109,15 @@ public class ClassPathExplorer { */ private static Map<String, URL> classpathLocations = getClasspathLocations(rawClasspathEntries); + private static boolean debug = false; + + static { + String debugProperty = System.getProperty("debug"); + if (debugProperty != null && !debugProperty.equals("")) { + debug = true; + } + } + /** * No instantiation from outside, callable methods are static. */ @@ -163,9 +170,8 @@ public class ClassPathExplorer { sb.append("\n"); } - final Logger logger = getLogger(); - logger.info(sb.toString()); - logger.info("Search took " + (end - start) + "ms"); + log(sb.toString()); + log("Search took " + (end - start) + "ms"); return new LocationInfo(widgetsets, themes); } @@ -226,8 +232,7 @@ public class ClassPathExplorer { } catch (MalformedURLException e) { // should never happen as based on an existing URL, // only changing end of file name/path part - getLogger().log(Level.SEVERE, - "Error locating the widgetset " + classname, e); + error("Error locating the widgetset " + classname, e); } } } @@ -276,7 +281,7 @@ public class ClassPathExplorer { } } } catch (IOException e) { - getLogger().log(Level.WARNING, "Error parsing jar file", e); + error("Error parsing jar file", e); } } @@ -304,7 +309,7 @@ public class ClassPathExplorer { classpath = classpath.substring(0, classpath.length() - 1); } - getLogger().log(Level.FINE, "Classpath: {0}", classpath); + debug("Classpath: " + classpath); String[] split = classpath.split(pathSep); for (int i = 0; i < split.length; i++) { @@ -338,9 +343,8 @@ public class ClassPathExplorer { include(null, file, locations); } long end = System.currentTimeMillis(); - Logger logger = getLogger(); - if (logger.isLoggable(Level.FINE)) { - logger.fine("getClassPathLocations took " + (end - start) + "ms"); + if (debug) { + debug("getClassPathLocations took " + (end - start) + "ms"); } return locations; } @@ -379,7 +383,8 @@ public class ClassPathExplorer { url = new URL("jar:" + url.toExternalForm() + "!/"); JarURLConnection conn = (JarURLConnection) url .openConnection(); - getLogger().fine(url.toString()); + debug(url.toString()); + JarFile jarFile = conn.getJarFile(); Manifest manifest = jarFile.getManifest(); if (manifest != null) { @@ -393,11 +398,13 @@ public class ClassPathExplorer { } } } catch (MalformedURLException e) { - getLogger().log(Level.FINEST, "Failed to inspect JAR file", - e); + if (debug) { + error("Failed to inspect JAR file", e); + } } catch (IOException e) { - getLogger().log(Level.FINEST, "Failed to inspect JAR file", - e); + if (debug) { + error("Failed to inspect JAR file", e); + } } return false; @@ -489,14 +496,12 @@ public class ClassPathExplorer { */ public static URL getDefaultSourceDirectory() { - final Logger logger = getLogger(); - - if (logger.isLoggable(Level.FINE)) { - logger.fine("classpathLocations values:"); + if (debug) { + debug("classpathLocations values:"); ArrayList<String> locations = new ArrayList<String>( classpathLocations.keySet()); for (String location : locations) { - logger.fine(String.valueOf(classpathLocations.get(location))); + debug(String.valueOf(classpathLocations.get(location))); } } @@ -510,11 +515,15 @@ public class ClassPathExplorer { try { return new URL("file://" + directory.getCanonicalPath()); } catch (MalformedURLException e) { - logger.log(Level.FINEST, "Ignoring exception", e); // ignore: continue to the next classpath entry + if (debug) { + e.printStackTrace(); + } } catch (IOException e) { - logger.log(Level.FINEST, "Ignoring exception", e); // ignore: continue to the next classpath entry + if (debug) { + e.printStackTrace(); + } } } } @@ -525,14 +534,24 @@ public class ClassPathExplorer { * Test method for helper tool */ public static void main(String[] args) { - getLogger().info( - "Searching for available widgetsets and stylesheets..."); + log("Searching for available widgetsets and stylesheets..."); ClassPathExplorer.getAvailableWidgetSetsAndStylesheets(); } - private static final Logger getLogger() { - return Logger.getLogger(ClassPathExplorer.class.getName()); + private static void log(String message) { + System.out.println(message); + } + + private static void error(String message, Exception e) { + System.err.println(message); + e.printStackTrace(); + } + + private static void debug(String message) { + if (debug) { + System.out.println(message); + } } } diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java index 61bcf00ad8..33aa689a88 100644 --- a/server/src/com/vaadin/ui/AbstractComponent.java +++ b/server/src/com/vaadin/ui/AbstractComponent.java @@ -31,13 +31,13 @@ import com.vaadin.event.ConnectorActionManager; import com.vaadin.event.ShortcutListener; import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.ComponentSizeValidator; -import com.vaadin.server.ErrorHandler; import com.vaadin.server.ErrorMessage; import com.vaadin.server.Resource; import com.vaadin.server.VaadinSession; import com.vaadin.shared.AbstractComponentState; import com.vaadin.shared.ComponentConstants; import com.vaadin.shared.ui.ComponentStateUtil; +import com.vaadin.ui.Field.ValueChangeEvent; import com.vaadin.util.ReflectTools; /** @@ -85,8 +85,6 @@ public abstract class AbstractComponent extends AbstractClientConnector private static final Pattern sizePattern = Pattern .compile("^(-?\\d+(\\.\\d+)?)(%|px|em|rem|ex|in|cm|mm|pt|pc)?$"); - private ErrorHandler errorHandler = null; - /** * Keeps track of the Actions added to this component; the actual * handling/notifying is delegated, usually to the containing window. @@ -97,6 +95,8 @@ public abstract class AbstractComponent extends AbstractClientConnector private HasComponents parent; + private Boolean explicitImmediateValue; + /* Constructor */ /** @@ -360,25 +360,29 @@ public abstract class AbstractComponent extends AbstractClientConnector } } - /* - * Tests if the component is in the immediate mode. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ public boolean isImmediate() { - return getState(false).immediate; + if (explicitImmediateValue != null) { + return explicitImmediateValue; + } else if (hasListeners(ValueChangeEvent.class)) { + /* + * Automatic immediate for fields that developers are interested + * about. + */ + return true; + } else { + return false; + } } /** - * Sets the component's immediate mode to the specified status. This method - * will trigger a {@link RepaintRequestEvent}. + * Sets the component's immediate mode to the specified status. * * @param immediate * the boolean value specifying if the component should be in the * immediate mode after the call. - * @see Component#isImmediate() */ public void setImmediate(boolean immediate) { + explicitImmediateValue = immediate; getState().immediate = immediate; } @@ -675,6 +679,8 @@ public abstract class AbstractComponent extends AbstractClientConnector } else { getState().errorMessage = null; } + + getState().immediate = isImmediate(); } /* General event framework */ diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java index 6a52d6b849..300e130c4e 100644 --- a/server/src/com/vaadin/ui/AbstractField.java +++ b/server/src/com/vaadin/ui/AbstractField.java @@ -783,15 +783,16 @@ public abstract class AbstractField<T> extends AbstractComponent implements ConversionException e) { String conversionError = getConversionError(); - if (dataSourceType != null) { - conversionError = conversionError.replace("{0}", - dataSourceType.getSimpleName()); - } - if (e != null) { - conversionError = conversionError.replace("{1}", - e.getLocalizedMessage()); + if (conversionError != null) { + if (dataSourceType != null) { + conversionError = conversionError.replace("{0}", + dataSourceType.getSimpleName()); + } + if (e != null) { + conversionError = conversionError.replace("{1}", + e.getLocalizedMessage()); + } } - return conversionError; } @@ -1085,6 +1086,8 @@ public abstract class AbstractField<T> extends AbstractComponent implements public void addValueChangeListener(Property.ValueChangeListener listener) { addListener(AbstractField.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); + // ensure "automatic immediate handling" works + markAsDirty(); } /** @@ -1106,6 +1109,8 @@ public abstract class AbstractField<T> extends AbstractComponent implements public void removeValueChangeListener(Property.ValueChangeListener listener) { removeListener(AbstractField.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); + // ensure "automatic immediate handling" works + markAsDirty(); } /** diff --git a/server/src/com/vaadin/ui/AbstractSelect.java b/server/src/com/vaadin/ui/AbstractSelect.java index 556b16943f..a32d40b11d 100644 --- a/server/src/com/vaadin/ui/AbstractSelect.java +++ b/server/src/com/vaadin/ui/AbstractSelect.java @@ -878,6 +878,37 @@ public abstract class AbstractSelect extends AbstractField<Object> implements return retval; } + /** + * Adds given items with given item ids to container. + * + * @since 7.2 + * @param itemId + * item identifiers to be added to underlying container + * @throws UnsupportedOperationException + * if the underlying container don't support adding items with + * identifiers + */ + public void addItems(Object... itemId) throws UnsupportedOperationException { + for (Object id : itemId) { + addItem(id); + } + } + + /** + * Adds given items with given item ids to container. + * + * @since 7.2 + * @param itemIds + * item identifiers to be added to underlying container + * @throws UnsupportedOperationException + * if the underlying container don't support adding items with + * identifiers + */ + public void addItems(Collection<Object> itemIds) + throws UnsupportedOperationException { + addItems(itemIds.toArray()); + } + /* * (non-Javadoc) * diff --git a/server/src/com/vaadin/ui/Calendar.java b/server/src/com/vaadin/ui/Calendar.java index 9ccc8ea2d9..b0999451c3 100644 --- a/server/src/com/vaadin/ui/Calendar.java +++ b/server/src/com/vaadin/ui/Calendar.java @@ -1824,7 +1824,7 @@ public class Calendar extends AbstractComponent implements try { Date start = formatter.parse(startDate); for (Action.Handler ah : actionHandlers) { - ah.handleAction(action, this, start); + ah.handleAction(action, Calendar.this, start); } } catch (ParseException e) { @@ -1842,7 +1842,7 @@ public class Calendar extends AbstractComponent implements DateConstants.ACTION_DATE_FORMAT_PATTERN); formatter.setTimeZone(getTimeZone()); for (Action.Handler ah : actionHandlers) { - ah.handleAction(action, this, events.get(eventIndex)); + ah.handleAction(action, Calendar.this, events.get(eventIndex)); } } } diff --git a/server/src/com/vaadin/ui/ComboBox.java b/server/src/com/vaadin/ui/ComboBox.java index 88e895df82..5fb2f81011 100644 --- a/server/src/com/vaadin/ui/ComboBox.java +++ b/server/src/com/vaadin/ui/ComboBox.java @@ -56,8 +56,6 @@ public class ComboBox extends AbstractSelect implements */ protected int pageLength = 10; - private int columns = 0; - // Current page when the user is 'paging' trough options private int currentPage = -1; diff --git a/server/src/com/vaadin/ui/FormLayout.java b/server/src/com/vaadin/ui/FormLayout.java index 9d5e637068..9dc0b24cad 100644 --- a/server/src/com/vaadin/ui/FormLayout.java +++ b/server/src/com/vaadin/ui/FormLayout.java @@ -52,4 +52,23 @@ public class FormLayout extends AbstractOrderedLayout { addComponents(children); } + /** + * @deprecated This method currently has no effect as expand ratios are not + * implemented in FormLayout + */ + @Override + @Deprecated + public void setExpandRatio(Component component, float ratio) { + super.setExpandRatio(component, ratio); + } + + /** + * @deprecated This method currently has no effect as expand ratios are not + * implemented in FormLayout + */ + @Override + @Deprecated + public float getExpandRatio(Component component) { + return super.getExpandRatio(component); + } } diff --git a/server/src/com/vaadin/ui/Label.java b/server/src/com/vaadin/ui/Label.java index d7cee2a80d..3aa83de420 100644 --- a/server/src/com/vaadin/ui/Label.java +++ b/server/src/com/vaadin/ui/Label.java @@ -18,7 +18,6 @@ package com.vaadin.ui; import java.lang.reflect.Method; import java.util.Locale; -import java.util.logging.Logger; import com.vaadin.data.Property; import com.vaadin.data.util.AbstractProperty; @@ -56,9 +55,6 @@ public class Label extends AbstractComponent implements Property<String>, Property.Viewer, Property.ValueChangeListener, Property.ValueChangeNotifier, Comparable<Label> { - private static final Logger logger = Logger - .getLogger(Label.class.getName()); - /** * @deprecated As of 7.0, use {@link ContentMode#TEXT} instead */ diff --git a/server/src/com/vaadin/ui/PushConfiguration.java b/server/src/com/vaadin/ui/PushConfiguration.java index a592b39bef..49738c5aff 100644 --- a/server/src/com/vaadin/ui/PushConfiguration.java +++ b/server/src/com/vaadin/ui/PushConfiguration.java @@ -21,6 +21,7 @@ import java.util.Collection; import java.util.Collections; import com.vaadin.server.VaadinSession; +import com.vaadin.server.communication.AtmospherePushConnection; import com.vaadin.shared.communication.PushMode; import com.vaadin.shared.ui.ui.Transport; import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; @@ -170,20 +171,32 @@ class PushConfigurationImpl implements PushConfiguration { throw new IllegalArgumentException("Push mode cannot be null"); } - if (pushMode.isEnabled()) { - VaadinSession session = ui.getSession(); - if (session != null && !session.getService().ensurePushAvailable()) { - throw new IllegalStateException( - "Push is not available. See previous log messages for more information."); - } + VaadinSession session = ui.getSession(); + + if (session == null) { + throw new UIDetachedException( + "Cannot set the push mode for a detached UI"); + } + + assert session.hasLock(); + + if (pushMode.isEnabled() && !session.getService().ensurePushAvailable()) { + throw new IllegalStateException( + "Push is not available. See previous log messages for more information."); } - /* - * Client-side will open a new connection or disconnect the old - * connection, so there's nothing more to do on the server at this - * point. - */ - getState().mode = pushMode; + PushMode oldMode = getState().mode; + if (oldMode != pushMode) { + getState().mode = pushMode; + + if (!oldMode.isEnabled() && pushMode.isEnabled()) { + // The push connection is initially in a disconnected state; + // the client will establish the connection + ui.setPushConnection(new AtmospherePushConnection(ui)); + } + // Nothing to do here if disabling push; + // the client will close the connection + } } /* @@ -274,9 +287,8 @@ class PushConfigurationImpl implements PushConfiguration { @Override public Collection<String> getParameterNames() { - return Collections - .unmodifiableCollection(ui.getState(false).pushConfiguration.parameters - .keySet()); + return Collections.unmodifiableCollection(getState(false).parameters + .keySet()); } } diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java index 32ed738697..06e82dedcb 100644 --- a/server/src/com/vaadin/ui/Table.java +++ b/server/src/com/vaadin/ui/Table.java @@ -2165,7 +2165,6 @@ public class Table extends AbstractSelect implements Action.Container, // more efficient implementation for containers supporting access by // index - Container.Indexed indexed = ((Container.Indexed) items); List<?> itemIds = getItemIds(firstIndex, rows); for (int i = 0; i < rows && i < itemIds.size(); i++) { Object id = itemIds.get(i); diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index a292e6b829..e688c06061 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -55,6 +55,7 @@ import com.vaadin.server.communication.PushConnection; import com.vaadin.shared.Connector; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; +import com.vaadin.shared.communication.PushMode; import com.vaadin.shared.ui.ui.DebugWindowClientRpc; import com.vaadin.shared.ui.ui.DebugWindowServerRpc; import com.vaadin.shared.ui.ui.ScrollClientRpc; @@ -422,8 +423,9 @@ public abstract class UI extends AbstractSingleComponentContainer implements } else { if (session == null) { detach(); - // Close the push connection when UI is detached. Otherwise the + // Disable push when the UI is detached. Otherwise the // push connection and possibly VaadinSession will live on. + getPushConfiguration().setPushMode(PushMode.DISABLED); setPushConnection(null); } this.session = session; @@ -550,8 +552,6 @@ public abstract class UI extends AbstractSingleComponentContainer implements private transient PushConnection pushConnection = null; - private boolean hasPendingPush = false; - private LocaleService localeService = new LocaleService(this, getState(false).localeServiceState); @@ -1368,6 +1368,9 @@ public abstract class UI extends AbstractSingleComponentContainer implements * Pushes the pending changes and client RPC invocations of this UI to the * client-side. * <p> + * If push is enabled, but the push connection is not currently open, the + * push will be done when the connection is established. + * <p> * As with all UI methods, the session must be locked when calling this * method. It is also recommended that {@link UI#getCurrent()} is set up to * return this UI since writing the response may invoke logic in any @@ -1385,79 +1388,73 @@ public abstract class UI extends AbstractSingleComponentContainer implements */ public void push() { VaadinSession session = getSession(); - if (session != null) { - assert session.hasLock(); - - /* - * Purge the pending access queue as it might mark a connector as - * dirty when the push would otherwise be ignored because there are - * no changes to push. - */ - session.getService().runPendingAccessTasks(session); - - if (!getConnectorTracker().hasDirtyConnectors()) { - // Do not push if there is nothing to push - return; - } - if (!getPushConfiguration().getPushMode().isEnabled()) { - throw new IllegalStateException("Push not enabled"); - } + if (session == null) { + throw new UIDetachedException("Cannot push a detached UI"); + } + assert session.hasLock(); - if (pushConnection == null) { - hasPendingPush = true; - } else { - pushConnection.push(); - } - } else { - throw new UIDetachedException("Trying to push a detached UI"); + if (!getPushConfiguration().getPushMode().isEnabled()) { + throw new IllegalStateException("Push not enabled"); + } + assert pushConnection != null; + + /* + * Purge the pending access queue as it might mark a connector as dirty + * when the push would otherwise be ignored because there are no changes + * to push. + */ + session.getService().runPendingAccessTasks(session); + + if (!getConnectorTracker().hasDirtyConnectors()) { + // Do not push if there is nothing to push + return; } + + pushConnection.push(); } /** * Returns the internal push connection object used by this UI. This method - * should only be called by the framework. If the returned PushConnection is - * not null, it is guaranteed to have {@code isConnected() == true}. + * should only be called by the framework. * <p> * This method is not intended to be overridden. If it is overridden, care * should be taken since this method might be called in situations where * {@link UI#getCurrent()} does not return this UI. * - * @return the push connection used by this UI, <code>null</code> if there - * is no active push connection. + * @return the push connection used by this UI, or {@code null} if push is + * not available. */ public PushConnection getPushConnection() { - assert (pushConnection == null || pushConnection.isConnected()); + assert !(getPushConfiguration().getPushMode().isEnabled() && pushConnection == null); return pushConnection; } /** * Sets the internal push connection object used by this UI. This method - * should only be called by the framework. If {@pushConnection} is not null, - * its {@code isConnected()} must be true. + * should only be called by the framework. + * <p> + * The {@code pushConnection} argument must be non-null if and only if + * {@code getPushConfiguration().getPushMode().isEnabled()}. * * @param pushConnection * the push connection to use for this UI */ public void setPushConnection(PushConnection pushConnection) { - // If pushMode is disabled then there should never be a pushConnection - assert (pushConnection == null || getPushConfiguration().getPushMode() - .isEnabled()); - assert (pushConnection == null || pushConnection.isConnected()); + // If pushMode is disabled then there should never be a pushConnection; + // if enabled there should always be + assert (pushConnection == null) + ^ getPushConfiguration().getPushMode().isEnabled(); if (pushConnection == this.pushConnection) { return; } - if (this.pushConnection != null) { + if (this.pushConnection != null && this.pushConnection.isConnected()) { this.pushConnection.disconnect(); } this.pushConnection = pushConnection; - if (pushConnection != null && hasPendingPush) { - hasPendingPush = false; - pushConnection.push(); - } } /** diff --git a/server/src/com/vaadin/ui/Upload.java b/server/src/com/vaadin/ui/Upload.java index 08cabf979a..98f5d2ded9 100644 --- a/server/src/com/vaadin/ui/Upload.java +++ b/server/src/com/vaadin/ui/Upload.java @@ -28,6 +28,7 @@ import com.vaadin.server.NoOutputStreamException; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; import com.vaadin.server.StreamVariable.StreamingProgressEvent; +import com.vaadin.shared.ui.upload.UploadClientRpc; /** * Component for uploading files from client to server. @@ -107,11 +108,6 @@ public class Upload extends AbstractComponent implements Component.Focusable, private int nextid; /** - * Flag to indicate that submitting file has been requested. - */ - private boolean forceSubmit; - - /** * Creates a new instance of Upload. * * The receiver must be set before performing an upload. @@ -157,11 +153,6 @@ public class Upload extends AbstractComponent implements Component.Focusable, notStarted = false; return; } - if (forceSubmit) { - target.addAttribute("forceSubmit", true); - forceSubmit = true; - return; - } // The field should be focused if (focus) { target.addAttribute("focus", true); @@ -1011,12 +1002,11 @@ public class Upload extends AbstractComponent implements Component.Focusable, */ public void submitUpload() { markAsDirty(); - forceSubmit = true; + getRpcProxy(UploadClientRpc.class).submitUpload(); } @Override public void markAsDirty() { - forceSubmit = false; super.markAsDirty(); } diff --git a/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java b/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java index 5c78965092..5da0bdc8a2 100644 --- a/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java +++ b/server/tests/src/com/vaadin/data/util/TestIndexedContainer.java @@ -306,7 +306,7 @@ public class TestIndexedContainer extends AbstractInMemoryContainerTest { Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); EasyMock.replay(addListener); - Object itemId = container.addItemAt(1); + container.addItemAt(1); assertEquals(1, capturedEvent.getValue().getFirstIndex()); } diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java index 844ef705b1..4c132eba30 100644 --- a/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/SQLContainerTest.java @@ -1917,7 +1917,6 @@ public class SQLContainerTest { EasyMock.expect(delegate.getCountStatement()) .andAnswer(new IAnswer<StatementHelper>() { @Override - @SuppressWarnings("deprecation") public StatementHelper answer() throws Throwable { StatementHelper sh = new StatementHelper(); StringBuffer query = new StringBuffer( @@ -1990,7 +1989,6 @@ public class SQLContainerTest { EasyMock.expect(delegate.getCountStatement()) .andAnswer(new IAnswer<StatementHelper>() { @Override - @SuppressWarnings("deprecation") public StatementHelper answer() throws Throwable { StatementHelper sh = new StatementHelper(); StringBuffer query = new StringBuffer( @@ -2134,7 +2132,6 @@ public class SQLContainerTest { EasyMock.expect(delegate.getCountStatement()) .andAnswer(new IAnswer<StatementHelper>() { @Override - @SuppressWarnings("deprecation") public StatementHelper answer() throws Throwable { StatementHelper sh = new StatementHelper(); StringBuffer query = new StringBuffer( @@ -2213,7 +2210,6 @@ public class SQLContainerTest { EasyMock.expect(delegate.getCountStatement()) .andAnswer(new IAnswer<StatementHelper>() { @Override - @SuppressWarnings("deprecation") public StatementHelper answer() throws Throwable { StatementHelper sh = new StatementHelper(); StringBuffer query = new StringBuffer( @@ -2292,7 +2288,6 @@ public class SQLContainerTest { EasyMock.expect(delegate.getCountStatement()) .andAnswer(new IAnswer<StatementHelper>() { @Override - @SuppressWarnings("deprecation") public StatementHelper answer() throws Throwable { StatementHelper sh = new StatementHelper(); StringBuffer query = new StringBuffer( diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java index 8e8c83d234..110225e206 100644 --- a/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/TicketTests.java @@ -88,7 +88,6 @@ public class TicketTests { EasyMock.expect(delegate.getCountStatement()) .andAnswer(new IAnswer<StatementHelper>() { @Override - @SuppressWarnings("deprecation") public StatementHelper answer() throws Throwable { StatementHelper sh = new StatementHelper(); StringBuffer query = new StringBuffer( diff --git a/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/CompareTest.java b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/CompareTest.java new file mode 100644 index 0000000000..c8faa71e66 --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/sqlcontainer/filters/CompareTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.data.util.sqlcontainer.filters; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.util.filter.Compare; + +public class CompareTest { + + @Test + public void testEquals() { + Compare c1 = new Compare.Equal("prop1", "val1"); + Compare c2 = new Compare.Equal("prop1", "val1"); + Assert.assertTrue(c1.equals(c2)); + } + + @Test + public void testDifferentTypeEquals() { + Compare c1 = new Compare.Equal("prop1", "val1"); + Compare c2 = new Compare.Greater("prop1", "val1"); + Assert.assertFalse(c1.equals(c2)); + } + + @Test + public void testEqualsNull() { + Compare c1 = new Compare.Equal("prop1", "val1"); + Assert.assertFalse(c1.equals(null)); + } +} diff --git a/server/tests/src/com/vaadin/tests/event/EventRouterTest.java b/server/tests/src/com/vaadin/tests/event/EventRouterTest.java new file mode 100644 index 0000000000..dbbeaf778e --- /dev/null +++ b/server/tests/src/com/vaadin/tests/event/EventRouterTest.java @@ -0,0 +1,111 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.event; + +import java.lang.reflect.Method; + +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.event.EventRouter; +import com.vaadin.server.ErrorEvent; +import com.vaadin.server.ErrorHandler; +import com.vaadin.ui.Component; +import com.vaadin.ui.Component.Listener; +import com.vaadin.util.ReflectTools; + +/** + * Test EventRouter and related error handling. + */ +public class EventRouterTest { + + private static final Method COMPONENT_EVENT_METHOD = ReflectTools + .findMethod(Component.Listener.class, "componentEvent", + Component.Event.class); + + private EventRouter router; + private Component component; + private ErrorHandler errorHandler; + private Listener listener; + + @Before + public void createMocks() { + router = new EventRouter(); + component = EasyMock.createNiceMock(Component.class); + errorHandler = EasyMock.createMock(ErrorHandler.class); + listener = EasyMock.createMock(Component.Listener.class); + router.addListener(Component.Event.class, listener, + COMPONENT_EVENT_METHOD); + } + + @Test + public void fireEvent_noException_eventReceived() { + listener.componentEvent(EasyMock.<Component.Event> anyObject()); + + EasyMock.replay(component, listener, errorHandler); + router.fireEvent(new Component.Event(component), errorHandler); + EasyMock.verify(listener, errorHandler); + } + + @Test + public void fireEvent_exceptionFromListenerAndNoHandler_exceptionPropagated() { + listener.componentEvent(EasyMock.<Component.Event> anyObject()); + EasyMock.expectLastCall().andThrow( + new RuntimeException("listener failed")); + + EasyMock.replay(component, listener); + try { + router.fireEvent(new Component.Event(component)); + Assert.fail("Did not receive expected exception from listener"); + } catch (RuntimeException e) { + // e is a ListenerMethod@MethodException + Assert.assertEquals("listener failed", e.getCause().getMessage()); + } + EasyMock.verify(listener); + } + + @Test + public void fireEvent_exceptionFromListener_errorHandlerCalled() { + listener.componentEvent(EasyMock.<Component.Event> anyObject()); + EasyMock.expectLastCall().andThrow( + new RuntimeException("listener failed")); + errorHandler.error(EasyMock.<ErrorEvent> anyObject()); + + EasyMock.replay(component, listener, errorHandler); + router.fireEvent(new Component.Event(component), errorHandler); + EasyMock.verify(listener, errorHandler); + } + + @Test + public void fireEvent_multipleListenersAndException_errorHandlerCalled() { + Listener listener2 = EasyMock.createMock(Component.Listener.class); + router.addListener(Component.Event.class, listener2, + COMPONENT_EVENT_METHOD); + + listener.componentEvent(EasyMock.<Component.Event> anyObject()); + EasyMock.expectLastCall().andThrow( + new RuntimeException("listener failed")); + errorHandler.error(EasyMock.<ErrorEvent> anyObject()); + // second listener should be called despite an error in the first + listener2.componentEvent(EasyMock.<Component.Event> anyObject()); + + EasyMock.replay(component, listener, listener2, errorHandler); + router.fireEvent(new Component.Event(component), errorHandler); + EasyMock.verify(listener, listener2, errorHandler); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java index e5420b8921..0a36c7f7ce 100644 --- a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java +++ b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java @@ -42,6 +42,7 @@ public class TestClassesSerializable extends TestCase { "com\\.vaadin\\.event\\.FieldEvents", // "com\\.vaadin\\.event\\.LayoutEvents", // "com\\.vaadin\\.event\\.MouseEvents", // + "com\\.vaadin\\.event\\.UIEvents", // "com\\.vaadin\\.server\\.VaadinPortlet", // "com\\.vaadin\\.server\\.MockServletConfig", // "com\\.vaadin\\.server\\.MockServletContext", // @@ -49,6 +50,8 @@ public class TestClassesSerializable extends TestCase { "com\\.vaadin\\.server\\.communication\\.FileUploadHandler\\$SimpleMultiPartInputStream", // "com\\.vaadin\\.server\\.communication\\.PushRequestHandler.*", "com\\.vaadin\\.server\\.communication\\.PushHandler.*", // PushHandler + "com\\.vaadin\\.server\\.communication\\.DateSerializer", // + "com\\.vaadin\\.server\\.communication\\.JSONSerializer", // // and its inner classes do not need to be serializable "com\\.vaadin\\.util\\.SerializerHelper", // fully static // class level filtering, also affecting nested classes and diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValueConversionError.java b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValueConversionError.java index ad762f8931..887f1b8ff3 100644 --- a/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValueConversionError.java +++ b/server/tests/src/com/vaadin/tests/server/component/abstractfield/AbsFieldValueConversionError.java @@ -54,6 +54,21 @@ public class AbsFieldValueConversionError extends TestCase { } + public void testNullConversionMessages() { + TextField tf = new TextField(); + tf.setConverter(new StringToIntegerConverter()); + tf.setPropertyDataSource(new MethodProperty<String>(paulaBean, "age")); + tf.setConversionError(null); + tf.setValue("abc"); + try { + tf.validate(); + fail(); + } catch (InvalidValueException e) { + Assert.assertEquals(null, e.getMessage()); + } + + } + public void testDefaultConversionErrorMessage() { TextField tf = new TextField(); tf.setConverter(new StringToIntegerConverter()); diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractselect/TestVarargsItemAddition.java b/server/tests/src/com/vaadin/tests/server/component/abstractselect/TestVarargsItemAddition.java new file mode 100644 index 0000000000..5575b8fd3d --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/abstractselect/TestVarargsItemAddition.java @@ -0,0 +1,26 @@ +package com.vaadin.tests.server.component.abstractselect; + +import java.util.Collection; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.vaadin.ui.OptionGroup; + +public class TestVarargsItemAddition extends TestCase { + + public void itemAddition() throws Exception { + + OptionGroup optionGroup = new OptionGroup(); + + optionGroup.addItems("foo", "bar", "car"); + + Collection<?> itemIds = optionGroup.getItemIds(); + Assert.assertEquals(3, itemIds.size()); + Assert.assertTrue(itemIds.contains("foo")); + Assert.assertTrue(itemIds.contains("bar")); + Assert.assertTrue(itemIds.contains("car")); + + } +} diff --git a/shared/src/com/vaadin/shared/communication/PushConstants.java b/shared/src/com/vaadin/shared/communication/PushConstants.java index f16cbb7390..4b4f247e5f 100644 --- a/shared/src/com/vaadin/shared/communication/PushConstants.java +++ b/shared/src/com/vaadin/shared/communication/PushConstants.java @@ -27,8 +27,11 @@ public class PushConstants implements Serializable { /** * The size, in <b>bytes</b>, of the receiving buffer used by some servers. + * <p> + * Should not be set to a value equal to or greater than 32768 due to a + * Jetty 9.1 issue (see #13087) */ - public static final int WEBSOCKET_BUFFER_SIZE = 65536; + public static final int WEBSOCKET_BUFFER_SIZE = 16384; /** * The maximum size, in <b>characters</b>, of a websocket message fragment. diff --git a/shared/src/com/vaadin/shared/ui/ui/Transport.java b/shared/src/com/vaadin/shared/ui/ui/Transport.java index ea641c0a3c..ebc0ba3aea 100644 --- a/shared/src/com/vaadin/shared/ui/ui/Transport.java +++ b/shared/src/com/vaadin/shared/ui/ui/Transport.java @@ -30,7 +30,11 @@ public enum Transport { /** * HTTP streaming */ - STREAMING("streaming"); + STREAMING("streaming"), + /** + * HTTP long polling + */ + LONG_POLLING("long-polling"); private String identifier; diff --git a/shared/src/com/vaadin/shared/ui/upload/UploadClientRpc.java b/shared/src/com/vaadin/shared/ui/upload/UploadClientRpc.java new file mode 100644 index 0000000000..1757ddb001 --- /dev/null +++ b/shared/src/com/vaadin/shared/ui/upload/UploadClientRpc.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.shared.ui.upload; + +import com.vaadin.shared.communication.ClientRpc; + +public interface UploadClientRpc extends ClientRpc { + + /** + * Forces the upload the send selected file to the server. + */ + void submitUpload(); +} diff --git a/theme-compiler/build.xml b/theme-compiler/build.xml index 03d0531a68..aed0f91fbb 100644 --- a/theme-compiler/build.xml +++ b/theme-compiler/build.xml @@ -20,8 +20,8 @@ </path> <path id="classpath.test.custom" /> - <!--<property name="classes.exclude" value="com/vaadin/buildhelpers/**" - /> --> + <property name="classes.exclude" value="**/*.properties"/> + <property name="extra.classes" value="${classes.exclude}"/> <target name="parser"> <!-- Copy javacc-5.0.jar to ${result.dir}/javacc/javacc.jar as the diff --git a/theme-compiler/src/com/vaadin/sass/CustomConsoleHandler.java b/theme-compiler/src/com/vaadin/sass/CustomConsoleHandler.java new file mode 100644 index 0000000000..44c9e345db --- /dev/null +++ b/theme-compiler/src/com/vaadin/sass/CustomConsoleHandler.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.sass; + +import java.io.PrintStream; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +/** + * + * @since + * @author Vaadin Ltd + */ +public class CustomConsoleHandler extends ConsoleHandler { + + private ConsoleHandler stdoutHandler; + + public CustomConsoleHandler() { + PrintStream err = System.err; + /* + * ConsoleHandler uses System.err to output all messages. Replace + * System.err temporary to construct ConsoleHandler and set it back + * after construction. + */ + System.setErr(System.out); + stdoutHandler = new ConsoleHandler(); + System.setErr(err); + } + + @Override + public void publish(LogRecord record) { + if (!Level.SEVERE.equals(record.getLevel())) { + stdoutHandler.publish(record); + } else { + super.publish(record); + } + } +} diff --git a/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java b/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java index ed6b98f5ac..63f59cdfab 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java +++ b/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java @@ -24,11 +24,13 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.logging.LogManager; import java.util.logging.Logger; import org.w3c.css.sac.CSSException; import org.w3c.css.sac.InputSource; +import com.vaadin.buildhelpers.CompileTheme; import com.vaadin.sass.internal.handler.SCSSDocumentHandler; import com.vaadin.sass.internal.handler.SCSSDocumentHandlerImpl; import com.vaadin.sass.internal.handler.SCSSErrorHandler; @@ -457,4 +459,19 @@ public class ScssStylesheet extends Node { public void setCharset(String charset) { this.charset = charset; } + + static { + String logFile = System.getProperty("java.util.logging.config.file"); + if (logFile == null) { + try { + LogManager.getLogManager().readConfiguration( + CompileTheme.class + .getResourceAsStream("/logging.properties")); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/expression/ArithmeticExpressionEvaluator.java b/theme-compiler/src/com/vaadin/sass/internal/expression/ArithmeticExpressionEvaluator.java index 7dbd8ae1a0..552b464941 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/expression/ArithmeticExpressionEvaluator.java +++ b/theme-compiler/src/com/vaadin/sass/internal/expression/ArithmeticExpressionEvaluator.java @@ -99,7 +99,8 @@ public class ArithmeticExpressionEvaluator { continue inputTermLoop; } } - throw new ArithmeticException(); + throw new ArithmeticException("Illegal arithmetic expression", + term); } if (current.getLexicalUnitType() == SCSSLexicalUnit.SCSS_OPERATOR_LEFT_PAREN) { operators.push(Parentheses.LEFT); @@ -115,7 +116,7 @@ public class ArithmeticExpressionEvaluator { while (!operators.isEmpty()) { Object operator = operators.pop(); if (operator == Parentheses.LEFT) { - throw new ArithmeticException("Unexpected \"(\" found"); + throw new ArithmeticException("Unexpected \"(\" found", term); } createNewOperand((BinaryOperator) operator, operands); } @@ -123,7 +124,7 @@ public class ArithmeticExpressionEvaluator { if (!operands.isEmpty()) { LexicalUnitImpl operand = (LexicalUnitImpl) operands.peek(); throw new ArithmeticException("Unexpected operand " - + operand.toString() + " found"); + + operand.toString() + " found", term); } return expression; } diff --git a/theme-compiler/src/com/vaadin/sass/internal/expression/exception/ArithmeticException.java b/theme-compiler/src/com/vaadin/sass/internal/expression/exception/ArithmeticException.java index 13b6f0e936..f9ab90fc32 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/expression/exception/ArithmeticException.java +++ b/theme-compiler/src/com/vaadin/sass/internal/expression/exception/ArithmeticException.java @@ -15,12 +15,28 @@ */ package com.vaadin.sass.internal.expression.exception; +import com.vaadin.sass.internal.parser.LexicalUnitImpl; + public class ArithmeticException extends RuntimeException { public ArithmeticException(String errorMsg) { super(errorMsg); } - public ArithmeticException() { - super("Illegal arithmetic expression"); + public ArithmeticException(String error, LexicalUnitImpl term) { + super(buildMessage(error, term)); + } + + private static String buildMessage(String message, LexicalUnitImpl term) { + StringBuilder builder = new StringBuilder(message); + + builder.append(": \""); + builder.append(term.toString()); + builder.append("\" ["); + builder.append(term.getLineNumber()); + builder.append(","); + builder.append(term.getColumnNumber()); + builder.append("]"); + + return builder.toString(); } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSDocumentHandler.java b/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSDocumentHandler.java index e6916e5070..3bf6c056c4 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSDocumentHandler.java +++ b/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSDocumentHandler.java @@ -51,8 +51,6 @@ public interface SCSSDocumentHandler extends DocumentHandler { void endNestedProperties(String name); - void includeDirective(String name, List<LexicalUnitImpl> args); - void importStyle(String uri, SACMediaList media, boolean isURL); void property(String name, LexicalUnitImpl value, boolean important, @@ -99,8 +97,8 @@ public interface SCSSDocumentHandler extends DocumentHandler { void contentDirective(); - void startIncludeContentBlock(String name, List<LexicalUnitImpl> args); + void startInclude(String name, List<LexicalUnitImpl> args); - void endIncludeContentBlock(); + void endInclude(); } diff --git a/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSDocumentHandlerImpl.java b/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSDocumentHandlerImpl.java index 99f00e3889..8c09e44f7c 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSDocumentHandlerImpl.java +++ b/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSDocumentHandlerImpl.java @@ -20,6 +20,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Stack; +import java.util.logging.Level; +import java.util.logging.Logger; import org.w3c.css.sac.CSSException; import org.w3c.css.sac.InputSource; @@ -98,7 +100,7 @@ public class SCSSDocumentHandlerImpl implements SCSSDocumentHandler { public ForNode forDirective(String var, String from, String to, boolean exclusive, String body) { ForNode node = new ForNode(var, from, to, exclusive, body); - System.out.println(node); + log(node); return node; } @@ -126,7 +128,7 @@ public class SCSSDocumentHandlerImpl implements SCSSDocumentHandler { @Override public WhileNode whileDirective(String condition, String body) { WhileNode node = new WhileNode(condition, body); - System.out.println(node); + log(node); return node; } @@ -138,14 +140,14 @@ public class SCSSDocumentHandlerImpl implements SCSSDocumentHandler { @Override public void ignorableAtRule(String atRule) throws CSSException { - System.out.println("ignorableAtRule(String atRule): " + atRule); + log("ignorableAtRule(String atRule): " + atRule); } @Override public void namespaceDeclaration(String prefix, String uri) throws CSSException { - System.out.println("namespaceDeclaration(String prefix, String uri): " - + prefix + ", " + uri); + log("namespaceDeclaration(String prefix, String uri): " + prefix + ", " + + uri); } @Override @@ -167,14 +169,14 @@ public class SCSSDocumentHandlerImpl implements SCSSDocumentHandler { @Override public void startPage(String name, String pseudo_page) throws CSSException { - System.out.println("startPage(String name, String pseudo_page): " - + name + ", " + pseudo_page); + log("startPage(String name, String pseudo_page): " + name + ", " + + pseudo_page); } @Override public void endPage(String name, String pseudo_page) throws CSSException { - System.out.println("endPage(String name, String pseudo_page): " + name - + ", " + pseudo_page); + log("endPage(String name, String pseudo_page): " + name + ", " + + pseudo_page); } @Override @@ -245,12 +247,6 @@ public class SCSSDocumentHandlerImpl implements SCSSDocumentHandler { } @Override - public void includeDirective(String name, List<LexicalUnitImpl> args) { - MixinNode node = new MixinNode(name, args); - nodeStack.peek().appendChild(node); - } - - @Override public void importStyle(String uri, SACMediaList media, boolean isURL) { ImportNode node = new ImportNode(uri, media, isURL); nodeStack.peek().appendChild(node); @@ -375,7 +371,7 @@ public class SCSSDocumentHandlerImpl implements SCSSDocumentHandler { } @Override - public void startIncludeContentBlock(String name, List<LexicalUnitImpl> args) { + public void startInclude(String name, List<LexicalUnitImpl> args) { MixinNode node = new MixinNode(name, args); nodeStack.peek().appendChild(node); nodeStack.push(node); @@ -383,7 +379,20 @@ public class SCSSDocumentHandlerImpl implements SCSSDocumentHandler { } @Override - public void endIncludeContentBlock() { + public void endInclude() { nodeStack.pop(); } + + private void log(Object object) { + if (object != null) { + log(object.toString()); + } else { + log(null); + } + } + + private void log(String msg) { + Logger.getLogger(SCSSDocumentHandlerImpl.class.getName()).log( + Level.INFO, msg); + } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSErrorHandler.java b/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSErrorHandler.java index 0d48da34e4..a7c65073ee 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSErrorHandler.java +++ b/theme-compiler/src/com/vaadin/sass/internal/handler/SCSSErrorHandler.java @@ -15,7 +15,8 @@ */ package com.vaadin.sass.internal.handler; -import java.io.PrintStream; +import java.util.logging.Level; +import java.util.logging.Logger; import org.w3c.css.sac.CSSException; import org.w3c.css.sac.CSSParseException; @@ -23,38 +24,33 @@ import org.w3c.css.sac.ErrorHandler; public class SCSSErrorHandler implements ErrorHandler { - private PrintStream errorStream; - - public SCSSErrorHandler(PrintStream errorStream) { - this.errorStream = errorStream; - } - public SCSSErrorHandler() { - this(System.out); } @Override public void error(CSSParseException arg0) throws CSSException { - errorStream.println("Error when parsing file \n" + arg0.getURI() - + " on line " + arg0.getLineNumber() + ", column " - + arg0.getColumnNumber()); - errorStream.println(arg0.getMessage() + "\n"); + log("Error when parsing file \n" + arg0.getURI() + " on line " + + arg0.getLineNumber() + ", column " + arg0.getColumnNumber()); + log(arg0.getMessage() + "\n"); } @Override public void fatalError(CSSParseException arg0) throws CSSException { - errorStream.println("FATAL Error when parsing file \n" + arg0.getURI() - + " on line " + arg0.getLineNumber() + ", column " - + arg0.getColumnNumber()); - errorStream.println(arg0.getMessage() + "\n"); + log("FATAL Error when parsing file \n" + arg0.getURI() + " on line " + + arg0.getLineNumber() + ", column " + arg0.getColumnNumber()); + log(arg0.getMessage() + "\n"); } @Override public void warning(CSSParseException arg0) throws CSSException { - errorStream.println("Warning when parsing file \n" + arg0.getURI() - + " on line " + arg0.getLineNumber() + ", column " - + arg0.getColumnNumber()); - errorStream.println(arg0.getMessage() + "\n"); + log("Warning when parsing file \n" + arg0.getURI() + " on line " + + arg0.getLineNumber() + ", column " + arg0.getColumnNumber()); + log(arg0.getMessage() + "\n"); + } + + private void log(String msg) { + Logger.getLogger(SCSSDocumentHandlerImpl.class.getName()).log( + Level.SEVERE, msg); } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/LexicalUnitImpl.java b/theme-compiler/src/com/vaadin/sass/internal/parser/LexicalUnitImpl.java index cfd428e094..96f841de0b 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/parser/LexicalUnitImpl.java +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/LexicalUnitImpl.java @@ -24,11 +24,22 @@ package com.vaadin.sass.internal.parser; import java.io.Serializable; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import org.w3c.css.sac.LexicalUnit; import com.vaadin.sass.internal.expression.exception.IncompatibleUnitsException; -import com.vaadin.sass.internal.util.ColorUtil; +import com.vaadin.sass.internal.parser.function.AbsFunctionGenerator; +import com.vaadin.sass.internal.parser.function.CeilFunctionGenerator; +import com.vaadin.sass.internal.parser.function.DarkenFunctionGenerator; +import com.vaadin.sass.internal.parser.function.DefaultFunctionGenerator; +import com.vaadin.sass.internal.parser.function.FloorFunctionGenerator; +import com.vaadin.sass.internal.parser.function.LightenFunctionGenerator; +import com.vaadin.sass.internal.parser.function.RoundFunctionGenerator; +import com.vaadin.sass.internal.parser.function.SCSSFunctionGenerator; import com.vaadin.sass.internal.util.DeepCopy; /** @@ -247,6 +258,9 @@ public class LexicalUnitImpl implements LexicalUnit, SCSSLexicalUnit, case SCSS_VARIABLE: text = "$" + s; break; + case SCSS_NULL: + text = ""; + break; case LexicalUnit.SAC_OPERATOR_COMMA: text = ","; break; @@ -322,30 +336,7 @@ public class LexicalUnitImpl implements LexicalUnit, SCSSLexicalUnit, case LexicalUnit.SAC_RECT_FUNCTION: case LexicalUnit.SAC_FUNCTION: String funcName = getFunctionName(); - LexicalUnitImpl firstParam = getParameters(); - if ("round".equals(funcName)) { - firstParam - .setFloatValue(Math.round(firstParam.getFloatValue())); - text = firstParam.toString(); - } else if ("ceil".equals(funcName)) { - firstParam.setFloatValue((float) Math.ceil(firstParam - .getFloatValue())); - text = firstParam.toString(); - } else if ("floor".equals(funcName)) { - firstParam.setFloatValue((float) Math.floor(firstParam - .getFloatValue())); - text = firstParam.toString(); - } else if ("abs".equals(funcName)) { - firstParam.setFloatValue(Math.abs(firstParam.getFloatValue())); - text = firstParam.toString(); - } else if ("darken".equals(funcName)) { - LexicalUnitImpl dark = ColorUtil.darken(this); - text = dark.toString(); - } else if ("lighten".equals(funcName)) { - text = ColorUtil.lighten(this).toString(); - } else { - text = getFunctionName() + "(" + getParameters() + ")"; - } + text = serializeFunction(funcName); break; case LexicalUnit.SAC_IDENT: text = getStringValue(); @@ -492,6 +483,11 @@ public class LexicalUnitImpl implements LexicalUnit, SCSSLexicalUnit, return new LexicalUnitImpl(line, column, previous, SCSS_VARIABLE, name); } + public static LexicalUnitImpl createNull(int line, int column, + LexicalUnitImpl previous) { + return new LexicalUnitImpl(line, column, previous, SCSS_NULL, "null"); + } + public static LexicalUnitImpl createNumber(int line, int column, LexicalUnitImpl previous, float v) { int i = (int) v; @@ -731,13 +727,6 @@ public class LexicalUnitImpl implements LexicalUnit, SCSSLexicalUnit, previous); } - @Override - public LexicalUnitImpl clone() { - LexicalUnitImpl cloned = new LexicalUnitImpl(type, line, column, prev); - cloned.replaceValue(this); - return cloned; - } - /** * Tries to return the value for this {@link LexicalUnitImpl} without * considering any related units. @@ -777,4 +766,38 @@ public class LexicalUnitImpl implements LexicalUnit, SCSSLexicalUnit, } } + + private String serializeFunction(String funcName) { + return getSerializer(funcName).printState(this); + } + + private static SCSSFunctionGenerator getSerializer(String funcName) { + SCSSFunctionGenerator serializer = SERIALIZERS.get(funcName); + if (serializer == null) { + return DEFAULT_SERIALIZER; + } else { + return serializer; + } + } + + private static List<SCSSFunctionGenerator> initSerializers() { + List<SCSSFunctionGenerator> list = new LinkedList<SCSSFunctionGenerator>(); + list.add(new AbsFunctionGenerator()); + list.add(new CeilFunctionGenerator()); + list.add(new DarkenFunctionGenerator()); + list.add(new FloorFunctionGenerator()); + list.add(new LightenFunctionGenerator()); + list.add(new RoundFunctionGenerator()); + return list; + } + + private static final Map<String, SCSSFunctionGenerator> SERIALIZERS = new HashMap<String, SCSSFunctionGenerator>(); + + private static final SCSSFunctionGenerator DEFAULT_SERIALIZER = new DefaultFunctionGenerator(); + + static { + for (SCSSFunctionGenerator serializer : initSerializers()) { + SERIALIZERS.put(serializer.getFunctionName(), serializer); + } + } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/LocatorImpl.java b/theme-compiler/src/com/vaadin/sass/internal/parser/LocatorImpl.java index ac244a9582..35589e0a94 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/parser/LocatorImpl.java +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/LocatorImpl.java @@ -23,8 +23,13 @@ */ package com.vaadin.sass.internal.parser; +import java.util.logging.Level; +import java.util.logging.Logger; + import org.w3c.css.sac.Locator; +import com.vaadin.sass.internal.handler.SCSSDocumentHandlerImpl; + /** * @version $Revision: 1.2 $ * @author Philippe Le Hegaret @@ -51,14 +56,17 @@ public class LocatorImpl implements Locator { int line; int column; + @Override public String getURI() { return uri; } + @Override public int getLineNumber() { return line; } + @Override public int getColumnNumber() { return column; } @@ -68,7 +76,7 @@ public class LocatorImpl implements Locator { */ public LocatorImpl(Parser p) { if (W3CDebug) { - System.err.println("LocatorImpl::newLocator(" + p + ");"); + log("LocatorImpl::newLocator(" + p + ");"); } uri = p.source.getURI(); line = p.token.beginLine; @@ -80,8 +88,7 @@ public class LocatorImpl implements Locator { */ public LocatorImpl(Parser p, Token tok) { if (W3CDebug) { - System.err.println("LocatorImpl::newLocator(" + p + ", " + tok - + ");"); + log("LocatorImpl::newLocator(" + p + ", " + tok + ");"); } uri = p.source.getURI(); line = tok.beginLine; @@ -93,8 +100,8 @@ public class LocatorImpl implements Locator { */ public LocatorImpl(Parser p, int line, int column) { if (W3CDebug) { - System.err.println("LocatorImpl::newLocator(" + p + ", " + line - + ", " + column + ");"); + log("LocatorImpl::newLocator(" + p + ", " + line + ", " + column + + ");"); } uri = p.source.getURI(); this.line = line; @@ -106,7 +113,7 @@ public class LocatorImpl implements Locator { */ public LocatorImpl reInit(Parser p) { if (W3CDebug) { - System.err.println("LocatorImpl::reInit(" + p + ");"); + log("LocatorImpl::reInit(" + p + ");"); } uri = p.source.getURI(); line = p.token.beginLine; @@ -119,7 +126,7 @@ public class LocatorImpl implements Locator { */ public LocatorImpl reInit(Parser p, Token tok) { if (W3CDebug) { - System.err.println("LocatorImpl::reInit(" + p + ", " + tok + ");"); + log("LocatorImpl::reInit(" + p + ", " + tok + ");"); } uri = p.source.getURI(); line = tok.beginLine; @@ -132,12 +139,16 @@ public class LocatorImpl implements Locator { */ public LocatorImpl reInit(Parser p, int line, int column) { if (W3CDebug) { - System.err.println("LocatorImpl::reInit(" + p + ", " + line + ", " - + column + ");"); + log("LocatorImpl::reInit(" + p + ", " + line + ", " + column + ");"); } uri = p.source.getURI(); this.line = line; this.column = column; return this; } + + private void log(String msg) { + Logger.getLogger(SCSSDocumentHandlerImpl.class.getName()).log( + Level.SEVERE, msg); + } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java index 53d1ee78ca..e68b24355b 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java @@ -16,38 +16,41 @@ /* Generated By:JavaCC: Do not edit this line. Parser.java */ package com.vaadin.sass.internal.parser; -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URL; +import java.io.*; +import java.net.*; import java.util.ArrayList; import java.util.Locale; +import java.util.Map; import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; -import org.w3c.css.sac.CSSException; -import org.w3c.css.sac.CSSParseException; import org.w3c.css.sac.ConditionFactory; +import org.w3c.css.sac.Condition; +import org.w3c.css.sac.SelectorFactory; +import org.w3c.css.sac.SelectorList; +import org.w3c.css.sac.Selector; +import org.w3c.css.sac.SimpleSelector; import org.w3c.css.sac.DocumentHandler; -import org.w3c.css.sac.ErrorHandler; import org.w3c.css.sac.InputSource; -import org.w3c.css.sac.LexicalUnit; +import org.w3c.css.sac.ErrorHandler; +import org.w3c.css.sac.CSSException; +import org.w3c.css.sac.CSSParseException; import org.w3c.css.sac.Locator; -import org.w3c.css.sac.SelectorFactory; -import org.w3c.css.sac.SelectorList; -import org.w3c.flute.parser.selectors.ConditionFactoryImpl; +import org.w3c.css.sac.LexicalUnit; + import org.w3c.flute.parser.selectors.SelectorFactoryImpl; +import org.w3c.flute.parser.selectors.ConditionFactoryImpl; + import org.w3c.flute.util.Encoding; -import com.vaadin.sass.internal.handler.SCSSDocumentHandlerImpl; -import com.vaadin.sass.internal.tree.Node; -import com.vaadin.sass.internal.tree.VariableNode; +import com.vaadin.sass.internal.handler.*; + +import com.vaadin.sass.internal.tree.*; /** * A CSS2 parser - * + * * @author Philippe Le H�garet * @version $Revision: 1.15 $ */ @@ -78,32 +81,27 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { /** * @@TODO - * @exception CSSException - * Not yet implemented + * @exception CSSException Not yet implemented */ - @Override public void setLocale(Locale locale) throws CSSException { throw new CSSException(CSSException.SAC_NOT_SUPPORTED_ERR); } - public InputSource getInputSource() { + public InputSource getInputSource(){ return source; } /** * Set the document handler for this parser */ - @Override public void setDocumentHandler(DocumentHandler handler) { - documentHandler = (SCSSDocumentHandlerImpl) handler; + this.documentHandler = (SCSSDocumentHandlerImpl) handler; } - @Override public void setSelectorFactory(SelectorFactory selectorFactory) { this.selectorFactory = selectorFactory; } - @Override public void setConditionFactory(ConditionFactory conditionFactory) { this.conditionFactory = conditionFactory; } @@ -111,24 +109,19 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { /** * Set the error handler for this parser */ - @Override public void setErrorHandler(ErrorHandler error) { - errorHandler = error; + this.errorHandler = error; } /** * Main parse methods - * - * @param source - * the source of the style sheet. - * @exception IOException - * the source can't be parsed. - * @exception CSSException - * the source is not CSS valid. + * + * @param source the source of the style sheet. + * @exception IOException the source can't be parsed. + * @exception CSSException the source is not CSS valid. */ - @Override - public void parseStyleSheet(InputSource source) throws CSSException, - IOException { + public void parseStyleSheet(InputSource source) + throws CSSException, IOException { this.source = source; ReInit(getCharStreamWithLurk(source)); if (selectorFactory == null) { @@ -143,34 +136,26 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { /** * Convenient method for URIs. - * - * @param systemId - * the fully resolved URI of the style sheet. - * @exception IOException - * the source can't be parsed. - * @exception CSSException - * the source is not CSS valid. + * + * @param systemId the fully resolved URI of the style sheet. + * @exception IOException the source can't be parsed. + * @exception CSSException the source is not CSS valid. */ - @Override - public void parseStyleSheet(String systemId) throws CSSException, - IOException { + public void parseStyleSheet(String systemId) + throws CSSException, IOException { parseStyleSheet(new InputSource(systemId)); } /** - * This method parses only one rule (style rule or at-rule, except - * @charset). - * - * @param source - * the source of the rule. - * @exception IOException - * the source can't be parsed. - * @exception CSSException - * the source is not CSS valid. + * This method parses only one rule (style rule or at-rule, except @charset). + * + * @param source the source of the rule. + * @exception IOException the source can't be parsed. + * @exception CSSException the source is not CSS valid. */ // TODO required by original parser but not used by Vaadin? - @Override - public void parseRule(InputSource source) throws CSSException, IOException { + public void parseRule(InputSource source) + throws CSSException, IOException { this.source = source; ReInit(getCharStreamWithLurk(source)); @@ -186,17 +171,13 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { /** * This method parses a style declaration (including the surrounding curly * braces). - * - * @param source - * the source of the style declaration. - * @exception IOException - * the source can't be parsed. - * @exception CSSException - * the source is not CSS valid. + * + * @param source the source of the style declaration. + * @exception IOException the source can't be parsed. + * @exception CSSException the source is not CSS valid. */ - @Override - public void parseStyleDeclaration(InputSource source) throws CSSException, - IOException { + public void parseStyleDeclaration(InputSource source) + throws CSSException, IOException { this.source = source; ReInit(getCharStreamWithLurk(source)); @@ -211,10 +192,8 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { /** * This methods returns "http://www.w3.org/TR/REC-CSS2". - * * @return the string "http://www.w3.org/TR/REC-CSS2". */ - @Override public String getParserVersion() { return "http://www.w3.org/TR/REC-CSS2"; } @@ -222,8 +201,8 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { /** * Parse methods used by DOM Level 2 implementation. */ - public void parseImportRule(InputSource source) throws CSSException, - IOException { + public void parseImportRule(InputSource source) + throws CSSException, IOException { this.source = source; ReInit(getCharStreamWithLurk(source)); @@ -236,8 +215,8 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { _parseImportRule(); } - public void parseMediaRule(InputSource source) throws CSSException, - IOException { + public void parseMediaRule(InputSource source) + throws CSSException, IOException { this.source = source; ReInit(getCharStreamWithLurk(source)); @@ -250,16 +229,14 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { _parseMediaRule(); } - @Override - public SelectorList parseSelectors(InputSource source) throws CSSException, - IOException { + public SelectorList parseSelectors(InputSource source) + throws CSSException, IOException { this.source = source; ReInit(getCharStreamWithLurk(source)); return null; } - @Override public LexicalUnit parsePropertyValue(InputSource source) throws CSSException, IOException { this.source = source; @@ -268,9 +245,8 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { return expr(); } - @Override - public boolean parsePriority(InputSource source) throws CSSException, - IOException { + public boolean parsePriority(InputSource source) + throws CSSException, IOException { this.source = source; ReInit(getCharStreamWithLurk(source)); @@ -278,8 +254,7 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { } /** - * Convert the source into a Reader. Used only by DOM Level 2 parser - * methods. + * Convert the source into a Reader. Used only by DOM Level 2 parser methods. */ private Reader getReader(InputSource source) throws IOException { if (source.getCharacterStream() != null) { @@ -291,7 +266,7 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { return new InputStreamReader(source.getByteStream(), "ASCII"); } else { return new InputStreamReader(source.getByteStream(), - source.getEncoding()); + source.getEncoding()); } } else { // systemId @@ -301,10 +276,11 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { } /** - * Convert the source into a CharStream with encoding informations. The - * encoding can be found in the InputSource or in the CSS document. Since - * this method marks the reader and make a reset after looking for the - * charset declaration, you'll find the charset declaration into the stream. + * Convert the source into a CharStream with encoding informations. + * The encoding can be found in the InputSource or in the CSS document. + * Since this method marks the reader and make a reset after looking for + * the charset declaration, you'll find the charset declaration into the + * stream. */ private CharStream getCharStreamWithLurk(InputSource source) throws CSSException, IOException { @@ -324,7 +300,7 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { } } } - // use UTF-8 as the default encoding. + //use UTF-8 as the default encoding. String encoding = source.getEncoding(); InputStream input = source.getByteStream(); if (!input.markSupported()) { @@ -334,7 +310,7 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { } // Mark either the original stream or the wrapped stream input.mark(100); - if (encoding == null) { + if(encoding == null){ encoding = "ASCII"; char c = ' '; @@ -343,15 +319,14 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { if (c == '@') { // hum, is it a charset ? - int size = 100; + int size = 100; byte[] buf = new byte[size]; input.read(buf, 0, 7); String keyword = new String(buf, 0, 7); if (keyword.equals("charset")) { // Yes, this is the charset declaration ! - // here I don't use the right declaration : white space are - // ' '. + // here I don't use the right declaration : white space are ' '. while ((c = (char) input.read()) == ' ') { // find the first quote } @@ -378,17 +353,15 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { if (c != ';') { // no semi colon at the end ? throw new CSSException("invalid charset declaration: " - + "missing semi colon"); + + "missing semi colon"); } encoding = new String(buf, 0, i); if (source.getEncoding() != null) { // compare the two encoding informations. - // For example, I don't accept to have ASCII and after - // UTF-8. + // For example, I don't accept to have ASCII and after UTF-8. // Is it really good ? That is the question. if (!encoding.equals(source.getEncoding())) { - throw new CSSException( - "invalid encoding information."); + throw new CSSException("invalid encoding information."); } } } // else no charset declaration available @@ -398,7 +371,7 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { source.setEncoding(encoding); // set the real reader of this source. source.setCharacterStream(new InputStreamReader(source.getByteStream(), - Encoding.getJavaEncoding(encoding))); + Encoding.getJavaEncoding(encoding))); // reset the stream (leave the charset declaration in the stream). input.reset(); @@ -406,7 +379,6 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { } private LocatorImpl currentLocator; - private Locator getLocator() { if (currentLocator == null) { currentLocator = new LocatorImpl(this); @@ -414,7 +386,6 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { } return currentLocator.reInit(this); } - private LocatorImpl getLocator(Token save) { if (currentLocator == null) { currentLocator = new LocatorImpl(this, save); @@ -431,8 +402,8 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { if (pe.specialConstructor) { StringBuffer errorM = new StringBuffer(); if (pe.currentToken != null) { - errorM.append("encountered \u005c"").append( - pe.currentToken.next); + errorM.append("encountered \u005c"") + .append(pe.currentToken.next); } errorM.append('"'); if (pe.expectedTokenSequences.length != 0) { @@ -448,10 +419,10 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { } } errorHandler.error(new CSSParseException(errorM.toString(), - l, e)); + l, e)); } else { - errorHandler.error(new CSSParseException(e.getMessage(), l, - e)); + errorHandler.error(new CSSParseException(e.getMessage(), + l, e)); } } else if (e == null) { errorHandler.error(new CSSParseException("error", l, null)); @@ -462,5406 +433,5423 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { } private void reportWarningSkipText(Locator l, String text) { - if (errorHandler != null && text != null) { + if (errorHandler != null && text != null) { errorHandler.warning(new CSSParseException("Skipping: " + text, l)); } } - /* - * The grammar of CSS2 - */ +/* + * The grammar of CSS2 + */ - /** - * The main entry for the parser. - * - * @exception ParseException - * exception during the parse - */ - final public void parserUnit() throws ParseException { - try { - documentHandler.startDocument(source); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CHARSET_SYM: - charset(); - break; - default: - jj_la1[0] = jj_gen; - ; - } - label_1: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - case CDO: - case CDC: - case ATKEYWORD: - ; - break; - default: - jj_la1[1] = jj_gen; - break label_1; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - jj_consume_token(S); - comments(); - break; - case CDO: - case CDC: - case ATKEYWORD: - ignoreStatement(); - break; - default: - jj_la1[2] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - label_2: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IMPORT_SYM: - ; - break; - default: - jj_la1[3] = jj_gen; - break label_2; - } - importDeclaration(); - label_3: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CDO: - case CDC: - case ATKEYWORD: - ; - break; - default: - jj_la1[4] = jj_gen; - break label_3; - } - ignoreStatement(); - label_4: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[5] = jj_gen; - break label_4; - } - jj_consume_token(S); - } - } - } - afterImportDeclaration(); - jj_consume_token(0); - } finally { - documentHandler.endDocument(source); +/** + * The main entry for the parser. + * + * @exception ParseException exception during the parse + */ + final public void parserUnit() throws ParseException { + try { + documentHandler.startDocument(source); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case CHARSET_SYM: + charset(); + break; + default: + jj_la1[0] = jj_gen; + ; + } + label_1: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + case CDO: + case CDC: + case ATKEYWORD: + ; + break; + default: + jj_la1[1] = jj_gen; + break label_1; } - } - - final public void charset() throws ParseException { - Token n; - try { - jj_consume_token(CHARSET_SYM); - label_5: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[6] = jj_gen; - break label_5; - } - jj_consume_token(S); - } - n = jj_consume_token(STRING); - label_6: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[7] = jj_gen; - break label_6; - } - jj_consume_token(S); - } - jj_consume_token(SEMICOLON); - } catch (ParseException e) { - reportError(getLocator(e.currentToken.next), e); - skipStatement(); - // reportWarningSkipText(getLocator(), skipStatement()); - - } catch (Exception e) { - reportError(getLocator(), e); - skipStatement(); - // reportWarningSkipText(getLocator(), skipStatement()); - + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + jj_consume_token(S); + comments(); + break; + case CDO: + case CDC: + case ATKEYWORD: + ignoreStatement(); + break; + default: + jj_la1[2] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + label_2: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IMPORT_SYM: + ; + break; + default: + jj_la1[3] = jj_gen; + break label_2; } - } - - final public void afterImportDeclaration() throws ParseException { - String ret; - Locator l; - label_7: while (true) { + importDeclaration(); + label_3: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case CDO: + case CDC: + case ATKEYWORD: ; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case DEBUG_SYM: - case WARN_SYM: - debuggingDirective(); - break; - case MIXIN_SYM: - mixinDirective(); - break; - case EACH_SYM: - case IF_SYM: - controlDirective(); - break; - case INCLUDE_SYM: - includeDirective(); - break; - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case IDENT: - case HASH: - styleRule(); - break; - case MEDIA_SYM: - media(); - break; - case PAGE_SYM: - page(); - break; - case FONT_FACE_SYM: - fontFace(); - break; - case KEY_FRAME_SYM: - keyframes(); - break; + break; + default: + jj_la1[4] = jj_gen; + break label_3; + } + ignoreStatement(); + label_4: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[8] = jj_gen; - if (jj_2_1(2147483647)) { - variable(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case VARIABLE: - listModifyDirective(); - break; - default: - jj_la1[9] = jj_gen; - l = getLocator(); - ret = skipStatement(); - if ((ret == null) || (ret.length() == 0)) { - { - if (true) { - return; - } - } - } - if (ret.charAt(0) == '@') { - documentHandler.unrecognizedRule(ret); - } else { - reportWarningSkipText(l, ret); - } - } - } - } - label_8: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CDO: - case CDC: - case ATKEYWORD: - ; - break; - default: - jj_la1[10] = jj_gen; - break label_8; - } - ignoreStatement(); - label_9: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[11] = jj_gen; - break label_9; - } - jj_consume_token(S); - } + jj_la1[5] = jj_gen; + break label_4; } - } - } - - final public void ignoreStatement() throws ParseException { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CDO: - jj_consume_token(CDO); + jj_consume_token(S); + } + } + } + afterImportDeclaration(); + jj_consume_token(0); + } finally { + documentHandler.endDocument(source); + } + } + + final public void charset() throws ParseException { + Token n; + try { + jj_consume_token(CHARSET_SYM); + label_5: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[6] = jj_gen; + break label_5; + } + jj_consume_token(S); + } + n = jj_consume_token(STRING); + label_6: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[7] = jj_gen; + break label_6; + } + jj_consume_token(S); + } + jj_consume_token(SEMICOLON); + } catch (ParseException e) { + reportError(getLocator(e.currentToken.next), e); + skipStatement(); + // reportWarningSkipText(getLocator(), skipStatement()); + + } catch (Exception e) { + reportError(getLocator(), e); + skipStatement(); + // reportWarningSkipText(getLocator(), skipStatement()); + + } + } + + final public void afterImportDeclaration() throws ParseException { + String ret; + Locator l; + label_7: + while (true) { + ; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DEBUG_SYM: + case WARN_SYM: + debuggingDirective(); + break; + case MIXIN_SYM: + mixinDirective(); + break; + case EACH_SYM: + case IF_SYM: + controlDirective(); + break; + case INCLUDE_SYM: + includeDirective(); + break; + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case IDENT: + case HASH: + styleRule(); + break; + case MEDIA_SYM: + media(); + break; + case PAGE_SYM: + page(); + break; + case FONT_FACE_SYM: + fontFace(); + break; + case KEY_FRAME_SYM: + keyframes(); + break; + default: + jj_la1[8] = jj_gen; + if (jj_2_1(2147483647)) { + variable(); + } else { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case VARIABLE: + listModifyDirective(); break; + default: + jj_la1[9] = jj_gen; + l = getLocator(); + ret = skipStatement(); + if ((ret == null) || (ret.length() == 0)) { + {if (true) return;} + } + if (ret.charAt(0) == '@') { + documentHandler.unrecognizedRule(ret); + } else { + reportWarningSkipText(l, ret); + } + } + } + } + label_8: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case CDO: case CDC: - jj_consume_token(CDC); - break; case ATKEYWORD: - atRuleDeclaration(); - break; + ; + break; default: - jj_la1[12] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); + jj_la1[10] = jj_gen; + break label_8; } - } - - /** - * The import statement - * - * @exception ParseException - * exception during the parse - */ - final public void importDeclaration() throws ParseException { - Token n; - String uri; - MediaListImpl ml = new MediaListImpl(); - boolean isURL = false; - try { - jj_consume_token(IMPORT_SYM); - label_10: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[13] = jj_gen; - break label_10; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case STRING: - n = jj_consume_token(STRING); - uri = convertStringIndex(n.image, 1, n.image.length() - 1); - break; - case URL: - n = jj_consume_token(URL); - isURL = true; - uri = n.image.substring(4, n.image.length() - 1).trim(); - if ((uri.charAt(0) == '"') || (uri.charAt(0) == '\u005c'')) { - uri = uri.substring(1, uri.length() - 1); - } - break; - default: - jj_la1[14] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - label_11: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[15] = jj_gen; - break label_11; - } - jj_consume_token(S); - } - mediaStatement(ml); - jj_consume_token(SEMICOLON); - label_12: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[16] = jj_gen; - break label_12; - } - jj_consume_token(S); - } - if (ml.getLength() == 0) { - // see section 6.3 of the CSS2 recommandation. - ml.addItem("all"); - } - documentHandler.importStyle(uri, ml, isURL); - } catch (ParseException e) { - reportError(getLocator(), e); - skipStatement(); - // reportWarningSkipText(getLocator(), skipStatement()); + ignoreStatement(); + label_9: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[11] = jj_gen; + break label_9; + } + jj_consume_token(S); + } + } + } + } + + final public void ignoreStatement() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case CDO: + jj_consume_token(CDO); + break; + case CDC: + jj_consume_token(CDC); + break; + case ATKEYWORD: + atRuleDeclaration(); + break; + default: + jj_la1[12] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } +/** + * The import statement + * + * @exception ParseException exception during the parse + */ + final public void importDeclaration() throws ParseException { + Token n; + String uri; + MediaListImpl ml = new MediaListImpl(); + boolean isURL = false; + try { + jj_consume_token(IMPORT_SYM); + label_10: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[13] = jj_gen; + break label_10; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case STRING: + n = jj_consume_token(STRING); + uri = convertStringIndex(n.image, 1, + n.image.length() -1); + break; + case URL: + n = jj_consume_token(URL); + isURL=true; + uri = n.image.substring(4, n.image.length()-1).trim(); + if ((uri.charAt(0) == '"') + || (uri.charAt(0) == '\u005c'')) { + uri = uri.substring(1, uri.length()-1); + } + break; + default: + jj_la1[14] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + label_11: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[15] = jj_gen; + break label_11; + } + jj_consume_token(S); + } + mediaStatement(ml); + jj_consume_token(SEMICOLON); + label_12: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[16] = jj_gen; + break label_12; } - } + jj_consume_token(S); + } + if (ml.getLength() == 0) { + // see section 6.3 of the CSS2 recommandation. + ml.addItem("all"); + } + documentHandler.importStyle(uri, ml, isURL); + } catch (ParseException e) { + reportError(getLocator(), e); + skipStatement(); + // reportWarningSkipText(getLocator(), skipStatement()); - /** - * @exception ParseException - * exception during the parse - */ - final public void keyframes() throws ParseException { - Token n; - boolean start = false; - String keyframeName = null; - String animationname = ""; - try { - n = jj_consume_token(KEY_FRAME_SYM); - label_13: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[17] = jj_gen; - break label_13; - } - jj_consume_token(S); - } - keyframeName = n.image; - label_14: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENT: - n = jj_consume_token(IDENT); - animationname += n.image; - break; - case INTERPOLATION: - n = jj_consume_token(INTERPOLATION); - animationname += n.image; - break; - default: - jj_la1[18] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - ; - break; - default: - jj_la1[19] = jj_gen; - break label_14; - } - } - label_15: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[20] = jj_gen; - break label_15; - } - jj_consume_token(S); - } - start = true; - documentHandler.startKeyFrames(keyframeName, animationname); - jj_consume_token(LBRACE); - label_16: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[21] = jj_gen; - break label_16; - } - jj_consume_token(S); - } - label_17: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case TO: - case FROM: - case CONTENT_SYM: - case PERCENTAGE: - ; - break; - default: - jj_la1[22] = jj_gen; - break label_17; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case TO: - case FROM: - case PERCENTAGE: - keyframeSelector(); - break; - case CONTENT_SYM: - contentDirective(); - break; - default: - jj_la1[23] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - jj_consume_token(RBRACE); - label_18: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[24] = jj_gen; - break label_18; - } - jj_consume_token(S); - } - } catch (ParseException e) { - reportError(getLocator(), e); - skipStatement(); - } finally { - if (start) { - documentHandler.endKeyFrames(); - } - } } + } - final public void keyframeSelector() throws ParseException { - Token n; - String selector = ""; - boolean start = false; - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case FROM: - n = jj_consume_token(FROM); - break; - case TO: - n = jj_consume_token(TO); - break; - case PERCENTAGE: - n = jj_consume_token(PERCENTAGE); - break; - default: - jj_la1[25] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - selector += n.image; - label_19: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[26] = jj_gen; - break label_19; - } - jj_consume_token(S); - } - label_20: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - jj_la1[27] = jj_gen; - break label_20; - } - jj_consume_token(COMMA); - label_21: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[28] = jj_gen; - break label_21; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case FROM: - n = jj_consume_token(FROM); - break; - case TO: - n = jj_consume_token(TO); - break; - case PERCENTAGE: - n = jj_consume_token(PERCENTAGE); - break; - default: - jj_la1[29] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - selector += (", " + n.image); - label_22: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[30] = jj_gen; - break label_22; - } - jj_consume_token(S); - } - } - jj_consume_token(LBRACE); - label_23: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[31] = jj_gen; - break label_23; - } - jj_consume_token(S); - } - start = true; - documentHandler.startKeyframeSelector(selector); - label_24: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case MICROSOFT_RULE: - case IDENT: - case VARIABLE: - case HASH: - case MEDIA_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ; - break; - default: - jj_la1[32] = jj_gen; - break label_24; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case IDENT: - case VARIABLE: - case HASH: - case MEDIA_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ifContentStatement(); - break; - case MICROSOFT_RULE: - microsoftExtension(); - break; - default: - jj_la1[33] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - jj_consume_token(RBRACE); - label_25: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[34] = jj_gen; - break label_25; - } - jj_consume_token(S); - } - } catch (ThrowedParseException e) { - if (errorHandler != null) { - LocatorImpl li = new LocatorImpl(this, - e.e.currentToken.next.beginLine, - e.e.currentToken.next.beginColumn - 1); - reportError(li, e.e); - } - } catch (ParseException e) { - reportError(getLocator(), e); - skipStatement(); - // reportWarningSkipText(getLocator(), skipStatement()); - - } catch (TokenMgrError e) { - reportWarningSkipText(getLocator(), skipStatement()); - } finally { - if (start) { - documentHandler.endKeyframeSelector(); - } +/** + * @exception ParseException exception during the parse + */ + final public void keyframes() throws ParseException { + Token n; + boolean start = false; + String keyframeName = null; + String animationname = ""; + try { + n = jj_consume_token(KEY_FRAME_SYM); + label_13: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[17] = jj_gen; + break label_13; + } + jj_consume_token(S); + } + keyframeName = n.image; + label_14: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENT: + n = jj_consume_token(IDENT); + animationname += n.image; + break; + case INTERPOLATION: + n = jj_consume_token(INTERPOLATION); + animationname += n.image; + break; + default: + jj_la1[18] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } - } - - /** - * @exception ParseException - * exception during the parse - */ - /* see http://www.w3.org/TR/css3-mediaqueries/ */ - final public void media() throws ParseException { - boolean start = false; - String ret; - MediaListImpl ml = new MediaListImpl(); - try { - jj_consume_token(MEDIA_SYM); - label_26: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[35] = jj_gen; - break label_26; - } - jj_consume_token(S); - } - mediaStatement(ml); - start = true; - documentHandler.startMedia(ml); - jj_consume_token(LBRACE); - label_27: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[36] = jj_gen; - break label_27; - } - jj_consume_token(S); - } - label_28: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CDO: - case LBRACE: - case DASHMATCH: - case INCLUDES: - case PLUS: - case MINUS: - case COMMA: - case SEMICOLON: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case NONASCII: - case DEBUG_SYM: - case WARN_SYM: - case STRING: - case IDENT: - case NUMBER: - case URL: - case PERCENTAGE: - case HASH: - case IMPORT_SYM: - case MEDIA_SYM: - case CHARSET_SYM: - case PAGE_SYM: - case FONT_FACE_SYM: - case ATKEYWORD: - case IMPORTANT_SYM: - case UNICODERANGE: - case FUNCTION: - case UNKNOWN: - ; - break; - default: - jj_la1[37] = jj_gen; - break label_28; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case DEBUG_SYM: - case WARN_SYM: - debuggingDirective(); - break; - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case IDENT: - case HASH: - styleRule(); - break; - case CDO: - case LBRACE: - case DASHMATCH: - case INCLUDES: - case MINUS: - case COMMA: - case SEMICOLON: - case NONASCII: - case STRING: - case NUMBER: - case URL: - case PERCENTAGE: - case IMPORT_SYM: - case MEDIA_SYM: - case CHARSET_SYM: - case PAGE_SYM: - case FONT_FACE_SYM: - case ATKEYWORD: - case IMPORTANT_SYM: - case UNICODERANGE: - case FUNCTION: - case UNKNOWN: - skipUnknownRule(); - break; - default: - jj_la1[38] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - jj_consume_token(RBRACE); - label_29: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[39] = jj_gen; - break label_29; - } - jj_consume_token(S); - } - } catch (ParseException e) { - reportError(getLocator(), e); - skipStatement(); - // reportWarningSkipText(getLocator(), skipStatement()); - - } finally { - if (start) { - documentHandler.endMedia(ml); - } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + ; + break; + default: + jj_la1[19] = jj_gen; + break label_14; } - } - - final public void mediaStatement(MediaListImpl ml) throws ParseException { - Token t; - t = getToken(1); - // loop over comma separated parts, add each to ml - while ((t.kind != LBRACE) && (t.kind != EOF) && (t.kind != SEMICOLON)) { - StringBuffer s = new StringBuffer(); - s.append(getToken(0).image); - while ((t.kind != COMMA) && (t.kind != LBRACE) && (t.kind != EOF) - && (t.kind != SEMICOLON)) { - s.append(t.image); - getNextToken(); - t = getToken(1); - } - if (t.kind == COMMA) { - // skip the comma and the token before it that is still the - // active token - getNextToken(); - getNextToken(); - t = getToken(1); - } - String str = s.toString().trim(); - if (str.length() > 0) { - ml.addItem(str); - } + } + label_15: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[20] = jj_gen; + break label_15; + } + jj_consume_token(S); + } + start = true; documentHandler.startKeyFrames(keyframeName, animationname); + jj_consume_token(LBRACE); + label_16: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[21] = jj_gen; + break label_16; + } + jj_consume_token(S); + } + label_17: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case TO: + case FROM: + case CONTENT_SYM: + case PERCENTAGE: + ; + break; + default: + jj_la1[22] = jj_gen; + break label_17; } - } - - /** - * @exception ParseException - * exception during the parse - */ - final public String medium() throws ParseException { - Token n; - n = jj_consume_token(IDENT); - { - if (true) { - return convertIdent(n.image); - } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case TO: + case FROM: + case PERCENTAGE: + keyframeSelector(); + break; + case CONTENT_SYM: + contentDirective(); + break; + default: + jj_la1[23] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + jj_consume_token(RBRACE); + label_18: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[24] = jj_gen; + break label_18; + } + jj_consume_token(S); + } + } catch (ParseException e) { + reportError(getLocator(), e); + skipStatement(); + } finally { + if (start) { + documentHandler.endKeyFrames(); + } + } + } + + final public void keyframeSelector() throws ParseException { + Token n; + String selector = ""; + boolean start = false; + try { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case FROM: + n = jj_consume_token(FROM); + break; + case TO: + n = jj_consume_token(TO); + break; + case PERCENTAGE: + n = jj_consume_token(PERCENTAGE); + break; + default: + jj_la1[25] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + selector += n.image; + label_19: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[26] = jj_gen; + break label_19; + } + jj_consume_token(S); + } + label_20: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[27] = jj_gen; + break label_20; } - throw new Error("Missing return statement in function"); - } - - /** - * @exception ParseException - * exception during the parse - */ - final public void page() throws ParseException { - boolean start = false; - Token n = null; - String page = null; - String pseudo = null; - try { - jj_consume_token(PAGE_SYM); - label_30: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[40] = jj_gen; - break label_30; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENT: - n = jj_consume_token(IDENT); - label_31: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[41] = jj_gen; - break label_31; - } - jj_consume_token(S); - } - break; - default: - jj_la1[42] = jj_gen; - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COLON: - pseudo = pseudo_page(); - break; - default: - jj_la1[43] = jj_gen; - ; - } - if (n != null) { - page = convertIdent(n.image); - } - jj_consume_token(LBRACE); - label_32: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[44] = jj_gen; - break label_32; - } - jj_consume_token(S); - } - start = true; - documentHandler.startPage(page, pseudo); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - declaration(); - break; - default: - jj_la1[45] = jj_gen; - ; - } - label_33: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - ; - break; - default: - jj_la1[46] = jj_gen; - break label_33; - } - jj_consume_token(SEMICOLON); - label_34: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[47] = jj_gen; - break label_34; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - declaration(); - break; - default: - jj_la1[48] = jj_gen; - ; - } - } - jj_consume_token(RBRACE); - label_35: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[49] = jj_gen; - break label_35; - } - jj_consume_token(S); - } - } catch (ParseException e) { - if (errorHandler != null) { - LocatorImpl li = new LocatorImpl(this, - e.currentToken.next.beginLine, - e.currentToken.next.beginColumn - 1); - reportError(li, e); - skipStatement(); - // reportWarningSkipText(li, skipStatement()); - } else { - skipStatement(); - } - } finally { - if (start) { - documentHandler.endPage(page, pseudo); - } + jj_consume_token(COMMA); + label_21: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[28] = jj_gen; + break label_21; + } + jj_consume_token(S); } - } - - final public String pseudo_page() throws ParseException { - Token n; - jj_consume_token(COLON); - n = jj_consume_token(IDENT); - label_36: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[50] = jj_gen; - break label_36; - } - jj_consume_token(S); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case FROM: + n = jj_consume_token(FROM); + break; + case TO: + n = jj_consume_token(TO); + break; + case PERCENTAGE: + n = jj_consume_token(PERCENTAGE); + break; + default: + jj_la1[29] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } - { - if (true) { - return convertIdent(n.image); - } + selector += (", " + n.image); + label_22: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[30] = jj_gen; + break label_22; + } + jj_consume_token(S); + } + } + jj_consume_token(LBRACE); + label_23: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[31] = jj_gen; + break label_23; + } + jj_consume_token(S); + } + start = true; + documentHandler.startKeyframeSelector(selector); + label_24: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case MICROSOFT_RULE: + case IDENT: + case VARIABLE: + case HASH: + case MEDIA_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ; + break; + default: + jj_la1[32] = jj_gen; + break label_24; } - throw new Error("Missing return statement in function"); - } - - final public void fontFace() throws ParseException { - boolean start = false; - try { - jj_consume_token(FONT_FACE_SYM); - label_37: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[51] = jj_gen; - break label_37; - } - jj_consume_token(S); - } - jj_consume_token(LBRACE); - label_38: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[52] = jj_gen; - break label_38; - } - jj_consume_token(S); - } - start = true; - documentHandler.startFontFace(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - declaration(); - break; - default: - jj_la1[53] = jj_gen; - ; - } - label_39: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - ; - break; - default: - jj_la1[54] = jj_gen; - break label_39; - } - jj_consume_token(SEMICOLON); - label_40: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[55] = jj_gen; - break label_40; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - declaration(); - break; - default: - jj_la1[56] = jj_gen; - ; - } - } - jj_consume_token(RBRACE); - label_41: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[57] = jj_gen; - break label_41; - } - jj_consume_token(S); - } - } catch (ParseException e) { - reportError(getLocator(), e); - skipStatement(); - // reportWarningSkipText(getLocator(), skipStatement()); - - } finally { - if (start) { - documentHandler.endFontFace(); - } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case IDENT: + case VARIABLE: + case HASH: + case MEDIA_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ifContentStatement(); + break; + case MICROSOFT_RULE: + microsoftExtension(); + break; + default: + jj_la1[33] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + jj_consume_token(RBRACE); + label_25: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[34] = jj_gen; + break label_25; } - } + jj_consume_token(S); + } + } catch (ThrowedParseException e) { + if (errorHandler != null) { + LocatorImpl li = new LocatorImpl(this, + e.e.currentToken.next.beginLine, + e.e.currentToken.next.beginColumn-1); + reportError(li, e.e); + } + } catch (ParseException e) { + reportError(getLocator(), e); + skipStatement(); + // reportWarningSkipText(getLocator(), skipStatement()); - /** - * @exception ParseException - * exception during the parse - */ - final public void atRuleDeclaration() throws ParseException { - Token n; - String ret; - n = jj_consume_token(ATKEYWORD); - ret = skipStatement(); - if ((ret != null) && (ret.charAt(0) == '@')) { - documentHandler.unrecognizedRule(ret); - } else { - reportWarningSkipText(getLocator(), ret); + } catch (TokenMgrError e) { + reportWarningSkipText(getLocator(), skipStatement()); + } finally { + if (start) { + documentHandler.endKeyframeSelector(); } } + } - final public void skipUnknownRule() throws ParseException { - Token n; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ATKEYWORD: - n = jj_consume_token(ATKEYWORD); - break; +/** + * @exception ParseException exception during the parse + */ +/* see http://www.w3.org/TR/css3-mediaqueries/ */ + final public void media() throws ParseException { + boolean start = false; + String ret; + MediaListImpl ml = new MediaListImpl(); + try { + jj_consume_token(MEDIA_SYM); + label_26: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[35] = jj_gen; + break label_26; + } + jj_consume_token(S); + } + mediaStatement(ml); + start = true; documentHandler.startMedia(ml); + jj_consume_token(LBRACE); + label_27: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[36] = jj_gen; + break label_27; + } + jj_consume_token(S); + } + label_28: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case CDO: - n = jj_consume_token(CDO); - break; - case CHARSET_SYM: - n = jj_consume_token(CHARSET_SYM); - break; - case COMMA: - n = jj_consume_token(COMMA); - break; + case LBRACE: case DASHMATCH: - n = jj_consume_token(DASHMATCH); - break; - case FONT_FACE_SYM: - n = jj_consume_token(FONT_FACE_SYM); - break; - case FUNCTION: - n = jj_consume_token(FUNCTION); - break; - case IMPORTANT_SYM: - n = jj_consume_token(IMPORTANT_SYM); - break; - case IMPORT_SYM: - n = jj_consume_token(IMPORT_SYM); - break; case INCLUDES: - n = jj_consume_token(INCLUDES); - break; - case LBRACE: - n = jj_consume_token(LBRACE); - break; - case MEDIA_SYM: - n = jj_consume_token(MEDIA_SYM); - break; + case PLUS: + case MINUS: + case COMMA: + case SEMICOLON: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: case NONASCII: - n = jj_consume_token(NONASCII); - break; + case DEBUG_SYM: + case WARN_SYM: + case CONTENT_SYM: + case STRING: + case IDENT: case NUMBER: - n = jj_consume_token(NUMBER); - break; - case PAGE_SYM: - n = jj_consume_token(PAGE_SYM); - break; + case URL: case PERCENTAGE: - n = jj_consume_token(PERCENTAGE); - break; - case STRING: - n = jj_consume_token(STRING); - break; + case HASH: + case IMPORT_SYM: + case MEDIA_SYM: + case CHARSET_SYM: + case PAGE_SYM: + case FONT_FACE_SYM: + case ATKEYWORD: + case IMPORTANT_SYM: case UNICODERANGE: - n = jj_consume_token(UNICODERANGE); - break; - case URL: - n = jj_consume_token(URL); - break; - case SEMICOLON: - n = jj_consume_token(SEMICOLON); - break; - case MINUS: - n = jj_consume_token(MINUS); - break; + case FUNCTION: case UNKNOWN: - n = jj_consume_token(UNKNOWN); - break; + ; + break; default: - jj_la1[58] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); + jj_la1[37] = jj_gen; + break label_28; + } + mediaDirective(); + } + jj_consume_token(RBRACE); + label_29: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[38] = jj_gen; + break label_29; + } + jj_consume_token(S); + } + } catch (ParseException e) { + reportError(getLocator(), e); + skipStatement(); + // reportWarningSkipText(getLocator(), skipStatement()); + + } finally { + if (start) { + documentHandler.endMedia(ml); + } + } + } + + final public void mediaDirective() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DEBUG_SYM: + case WARN_SYM: + debuggingDirective(); + break; + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case IDENT: + case HASH: + styleRule(); + break; + case CDO: + case LBRACE: + case DASHMATCH: + case INCLUDES: + case MINUS: + case COMMA: + case SEMICOLON: + case NONASCII: + case STRING: + case NUMBER: + case URL: + case PERCENTAGE: + case IMPORT_SYM: + case MEDIA_SYM: + case CHARSET_SYM: + case PAGE_SYM: + case FONT_FACE_SYM: + case ATKEYWORD: + case IMPORTANT_SYM: + case UNICODERANGE: + case FUNCTION: + case UNKNOWN: + skipUnknownRule(); + break; + case CONTENT_SYM: + contentDirective(); + break; + default: + jj_la1[39] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void mediaStatement(MediaListImpl ml) throws ParseException { + Token t; + t = getToken(1); + // loop over comma separated parts, add each to ml + while ((t.kind != LBRACE) && (t.kind != EOF) && (t.kind != SEMICOLON)) { + StringBuffer s = new StringBuffer(); + s.append(getToken(0).image); + while ((t.kind != COMMA) && (t.kind != LBRACE) && (t.kind != EOF) && (t.kind != SEMICOLON)) { + s.append(t.image); + getNextToken(); + t = getToken(1); } - String ret; - Locator loc = getLocator(); - ret = skipStatement(); - if ((ret != null) && (n.image.charAt(0) == '@')) { - documentHandler.unrecognizedRule(ret); - } else { - reportWarningSkipText(loc, ret); + if (t.kind == COMMA) { + // skip the comma and the token before it that is still the active token + getNextToken(); + getNextToken(); + t = getToken(1); } - } + String str = s.toString().trim(); + if (str.length() > 0) { + ml.addItem(str); + } + } + } - /** - * @exception ParseException - * exception during the parse - */ - final public char combinator() throws ParseException { - char connector = ' '; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - connector = combinatorChar(); - break; +/** + * @exception ParseException exception during the parse + */ + final public String medium() throws ParseException { + Token n; + n = jj_consume_token(IDENT); + {if (true) return convertIdent(n.image);} + throw new Error("Missing return statement in function"); + } + +/** + * @exception ParseException exception during the parse + */ + final public void page() throws ParseException { + boolean start = false; + Token n = null; + String page = null; + String pseudo = null; + try { + jj_consume_token(PAGE_SYM); + label_30: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case S: - jj_consume_token(S); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - connector = combinatorChar(); - break; - default: - jj_la1[59] = jj_gen; - ; - } - break; + ; + break; default: - jj_la1[60] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); + jj_la1[40] = jj_gen; + break label_30; } - { - if (true) { - return connector; - } - } - throw new Error("Missing return statement in function"); - } - - /** to refactor combinator and reuse in selector(). */ - final public char combinatorChar() throws ParseException { - Token t; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - t = jj_consume_token(PLUS); - break; - case PRECEDES: - t = jj_consume_token(PRECEDES); - break; - case SIBLING: - t = jj_consume_token(SIBLING); + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENT: + n = jj_consume_token(IDENT); + label_31: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; break; + default: + jj_la1[41] = jj_gen; + break label_31; + } + jj_consume_token(S); + } + break; + default: + jj_la1[42] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COLON: + pseudo = pseudo_page(); + break; + default: + jj_la1[43] = jj_gen; + ; + } + if (n != null) { + page = convertIdent(n.image); + } + jj_consume_token(LBRACE); + label_32: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[61] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - label_42: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[62] = jj_gen; - break label_42; - } - jj_consume_token(S); - } - { - if (true) { - return t.image.charAt(0); - } - } - throw new Error("Missing return statement in function"); - } - - final public void microsoftExtension() throws ParseException { - Token n; - String name = ""; - String value = ""; - // This is not really taking the syntax of filter rules into account - n = jj_consume_token(MICROSOFT_RULE); - label_43: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[63] = jj_gen; - break label_43; - } - jj_consume_token(S); - } - name = n.image; - jj_consume_token(COLON); - label_44: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENT: - n = jj_consume_token(IDENT); - value += n.image; - break; - case NUMBER: - n = jj_consume_token(NUMBER); - value += n.image; - break; - case STRING: - n = jj_consume_token(STRING); - value += n.image; - break; - case COMMA: - n = jj_consume_token(COMMA); - value += n.image; - break; - case INTERPOLATION: - n = jj_consume_token(INTERPOLATION); - value += n.image; - break; - case COLON: - n = jj_consume_token(COLON); - value += n.image; - break; - case FUNCTION: - n = jj_consume_token(FUNCTION); - value += n.image; - break; - case RPARAN: - n = jj_consume_token(RPARAN); - value += n.image; - break; - case EQ: - n = jj_consume_token(EQ); - value += n.image; - break; - case DOT: - n = jj_consume_token(DOT); - value += n.image; - break; - case S: - n = jj_consume_token(S); - if (value.lastIndexOf(' ') != value.length() - 1) { - value += n.image; - } - break; - default: - jj_la1[64] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - case EQ: - case COMMA: - case DOT: - case RPARAN: - case COLON: - case INTERPOLATION: - case STRING: - case IDENT: - case NUMBER: - case FUNCTION: - ; - break; - default: - jj_la1[65] = jj_gen; - break label_44; - } + jj_la1[44] = jj_gen; + break label_32; + } + jj_consume_token(S); + } + start = true; + documentHandler.startPage(page, pseudo); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + declaration(); + break; + default: + jj_la1[45] = jj_gen; + ; + } + label_33: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + ; + break; + default: + jj_la1[46] = jj_gen; + break label_33; } jj_consume_token(SEMICOLON); - label_45: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[66] = jj_gen; - break label_45; - } - jj_consume_token(S); - } - documentHandler.microsoftDirective(name, value); - } - - /** - * @exception ParseException - * exception during the parse - */ - final public String property() throws ParseException { - Token t; - String s = ""; - label_46: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENT: - t = jj_consume_token(IDENT); - s += t.image; - break; - case INTERPOLATION: - t = jj_consume_token(INTERPOLATION); - s += t.image; - break; - default: - jj_la1[67] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - ; - break; - default: - jj_la1[68] = jj_gen; - break label_46; - } - } - label_47: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[69] = jj_gen; - break label_47; - } - jj_consume_token(S); - } - { - if (true) { - return s; - } - } - throw new Error("Missing return statement in function"); - } - - final public String variableName() throws ParseException { - Token n; - n = jj_consume_token(VARIABLE); - label_48: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[70] = jj_gen; - break label_48; - } - jj_consume_token(S); + label_34: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[47] = jj_gen; + break label_34; + } + jj_consume_token(S); } - { - if (true) { - return convertIdent(n.image.substring(1)); - } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + declaration(); + break; + default: + jj_la1[48] = jj_gen; + ; + } + } + jj_consume_token(RBRACE); + label_35: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[49] = jj_gen; + break label_35; + } + jj_consume_token(S); + } + } catch (ParseException e) { + if (errorHandler != null) { + LocatorImpl li = new LocatorImpl(this, + e.currentToken.next.beginLine, + e.currentToken.next.beginColumn-1); + reportError(li, e); + skipStatement(); + // reportWarningSkipText(li, skipStatement()); + } else { + skipStatement(); + } + } finally { + if (start) { + documentHandler.endPage(page, pseudo); + } + } + } + + final public String pseudo_page() throws ParseException { + Token n; + jj_consume_token(COLON); + n = jj_consume_token(IDENT); + label_36: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[50] = jj_gen; + break label_36; + } + jj_consume_token(S); + } + {if (true) return convertIdent(n.image);} + throw new Error("Missing return statement in function"); + } + + final public void fontFace() throws ParseException { + boolean start = false; + try { + jj_consume_token(FONT_FACE_SYM); + label_37: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[51] = jj_gen; + break label_37; + } + jj_consume_token(S); + } + jj_consume_token(LBRACE); + label_38: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[52] = jj_gen; + break label_38; + } + jj_consume_token(S); + } + start = true; documentHandler.startFontFace(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + declaration(); + break; + default: + jj_la1[53] = jj_gen; + ; + } + label_39: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + ; + break; + default: + jj_la1[54] = jj_gen; + break label_39; } - throw new Error("Missing return statement in function"); - } - - final public String functionName() throws ParseException { - Token n; - n = jj_consume_token(FUNCTION); - label_49: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[71] = jj_gen; - break label_49; - } - jj_consume_token(S); + jj_consume_token(SEMICOLON); + label_40: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[55] = jj_gen; + break label_40; + } + jj_consume_token(S); } - { - if (true) { - return convertIdent(n.image.substring(0, n.image.length() - 1)); - } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + declaration(); + break; + default: + jj_la1[56] = jj_gen; + ; + } + } + jj_consume_token(RBRACE); + label_41: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[57] = jj_gen; + break label_41; } - throw new Error("Missing return statement in function"); - } + jj_consume_token(S); + } + } catch (ParseException e) { + reportError(getLocator(), e); + skipStatement(); + // reportWarningSkipText(getLocator(), skipStatement()); - /** - * @exception ParseException - * exception during the parse - */ - final public void styleRule() throws ParseException { - boolean start = false; - ArrayList<String> l = null; - Token save; - Locator loc; - try { - l = selectorList(); - save = token; - jj_consume_token(LBRACE); - label_50: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[72] = jj_gen; - break label_50; - } - jj_consume_token(S); - } - start = true; - documentHandler.startSelector(l); - label_51: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case MICROSOFT_RULE: - case IDENT: - case VARIABLE: - case HASH: - case IMPORT_SYM: - case MEDIA_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ; - break; - default: - jj_la1[73] = jj_gen; - break label_51; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case IDENT: - case VARIABLE: - case HASH: - case MEDIA_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ifContentStatement(); - break; - case MICROSOFT_RULE: - microsoftExtension(); - break; - case IMPORT_SYM: - importDeclaration(); - break; - default: - jj_la1[74] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - jj_consume_token(RBRACE); - label_52: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[75] = jj_gen; - break label_52; - } - jj_consume_token(S); - } - } catch (ThrowedParseException e) { - if (errorHandler != null) { - LocatorImpl li = new LocatorImpl(this, - e.e.currentToken.next.beginLine, - e.e.currentToken.next.beginColumn - 1); - reportError(li, e.e); - } - } catch (ParseException e) { - reportError(getLocator(), e); - skipStatement(); - // reportWarningSkipText(getLocator(), skipStatement()); - - } catch (TokenMgrError e) { - reportWarningSkipText(getLocator(), skipStatement()); - } finally { - if (start) { - documentHandler.endSelector(); - } - } + } finally { + if (start) { + documentHandler.endFontFace(); + } } + } - final public ArrayList<String> selectorList() throws ParseException { - ArrayList<String> selectors = new ArrayList<String>(); - String selector; - selector = selector(); - label_53: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - jj_la1[76] = jj_gen; - break label_53; - } - jj_consume_token(COMMA); - label_54: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[77] = jj_gen; - break label_54; - } - jj_consume_token(S); - } - selectors.add(selector); - selector = selector(); - } - selectors.add(selector); - { - if (true) { - return selectors; - } +/** + * @exception ParseException exception during the parse + */ + final public void atRuleDeclaration() throws ParseException { + Token n; + String ret; + n = jj_consume_token(ATKEYWORD); + ret=skipStatement(); + if ((ret != null) && (ret.charAt(0) == '@')) { + documentHandler.unrecognizedRule(ret); + } else { + reportWarningSkipText(getLocator(), ret); } - throw new Error("Missing return statement in function"); - } - - /** - * @exception ParseException - * exception during the parse - */ - final public String selector() throws ParseException { - String selector = null; - char comb; - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case IDENT: - case HASH: - selector = simple_selector(null, ' '); - break; - case PLUS: - case PRECEDES: - case SIBLING: - comb = combinatorChar(); - selector = simple_selector(selector, comb); - break; - default: - jj_la1[78] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - label_55: while (true) { - if (jj_2_2(2)) { - ; - } else { - break label_55; - } - comb = combinator(); - selector = simple_selector(selector, comb); - } - label_56: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[79] = jj_gen; - break label_56; - } - jj_consume_token(S); - } - { - if (true) { - return selector; - } - } - } catch (ParseException e) { - /* - * Token t = getToken(1); StringBuffer s = new StringBuffer(); - * s.append(getToken(0).image); while ((t.kind != COMMA) && (t.kind - * != SEMICOLON) && (t.kind != LBRACE) && (t.kind != EOF)) { - * s.append(t.image); getNextToken(); t = getToken(1); } - * reportWarningSkipText(getLocator(), s.toString()); - */ - Token t = getToken(1); - while ((t.kind != COMMA) && (t.kind != SEMICOLON) - && (t.kind != LBRACE) && (t.kind != EOF)) { - getNextToken(); - t = getToken(1); - } + } + + final public void skipUnknownRule() throws ParseException { + Token n; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ATKEYWORD: + n = jj_consume_token(ATKEYWORD); + break; + case CDO: + n = jj_consume_token(CDO); + break; + case CHARSET_SYM: + n = jj_consume_token(CHARSET_SYM); + break; + case COMMA: + n = jj_consume_token(COMMA); + break; + case DASHMATCH: + n = jj_consume_token(DASHMATCH); + break; + case FONT_FACE_SYM: + n = jj_consume_token(FONT_FACE_SYM); + break; + case FUNCTION: + n = jj_consume_token(FUNCTION); + break; + case IMPORTANT_SYM: + n = jj_consume_token(IMPORTANT_SYM); + break; + case IMPORT_SYM: + n = jj_consume_token(IMPORT_SYM); + break; + case INCLUDES: + n = jj_consume_token(INCLUDES); + break; + case LBRACE: + n = jj_consume_token(LBRACE); + break; + case MEDIA_SYM: + n = jj_consume_token(MEDIA_SYM); + break; + case NONASCII: + n = jj_consume_token(NONASCII); + break; + case NUMBER: + n = jj_consume_token(NUMBER); + break; + case PAGE_SYM: + n = jj_consume_token(PAGE_SYM); + break; + case PERCENTAGE: + n = jj_consume_token(PERCENTAGE); + break; + case STRING: + n = jj_consume_token(STRING); + break; + case UNICODERANGE: + n = jj_consume_token(UNICODERANGE); + break; + case URL: + n = jj_consume_token(URL); + break; + case SEMICOLON: + n = jj_consume_token(SEMICOLON); + break; + case MINUS: + n = jj_consume_token(MINUS); + break; + case UNKNOWN: + n = jj_consume_token(UNKNOWN); + break; + default: + jj_la1[58] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + String ret; + Locator loc = getLocator(); + ret=skipStatement(); + if ((ret != null) && (n.image.charAt(0) == '@')) { + documentHandler.unrecognizedRule(ret); + } else { + reportWarningSkipText(loc, ret); + } + } - { - if (true) { - throw new ThrowedParseException(e); - } - } - } - throw new Error("Missing return statement in function"); - } +/** + * @exception ParseException exception during the parse + */ + final public char combinator() throws ParseException { +char connector = ' '; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + connector = combinatorChar(); + break; + case S: + jj_consume_token(S); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + connector = combinatorChar(); + break; + default: + jj_la1[59] = jj_gen; + ; + } + break; + default: + jj_la1[60] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + {if (true) return connector;} + throw new Error("Missing return statement in function"); + } + +/**to refactor combinator and reuse in selector().*/ + final public char combinatorChar() throws ParseException { + Token t; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + t = jj_consume_token(PLUS); + break; + case PRECEDES: + t = jj_consume_token(PRECEDES); + break; + case SIBLING: + t = jj_consume_token(SIBLING); + break; + default: + jj_la1[61] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + label_42: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[62] = jj_gen; + break label_42; + } + jj_consume_token(S); + } + {if (true) return t.image.charAt(0);} + throw new Error("Missing return statement in function"); + } + + final public void microsoftExtension() throws ParseException { + Token n; + String name = ""; + String value = ""; + // This is not really taking the syntax of filter rules into account + n = jj_consume_token(MICROSOFT_RULE); + label_43: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[63] = jj_gen; + break label_43; + } + jj_consume_token(S); + } + name = n.image; + jj_consume_token(COLON); + label_44: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENT: + n = jj_consume_token(IDENT); + value += n.image; + break; + case NUMBER: + n = jj_consume_token(NUMBER); + value += n.image; + break; + case STRING: + n = jj_consume_token(STRING); + value += n.image; + break; + case COMMA: + n = jj_consume_token(COMMA); + value += n.image; + break; + case INTERPOLATION: + n = jj_consume_token(INTERPOLATION); + value += n.image; + break; + case COLON: + n = jj_consume_token(COLON); + value += n.image; + break; + case FUNCTION: + n = jj_consume_token(FUNCTION); + value += n.image; + break; + case RPARAN: + n = jj_consume_token(RPARAN); + value += n.image; + break; + case EQ: + n = jj_consume_token(EQ); + value += n.image; + break; + case DOT: + n = jj_consume_token(DOT); + value += n.image; + break; + case S: + n = jj_consume_token(S); + if(value.lastIndexOf(' ') != value.length()-1) + { value += n.image; } + break; + default: + jj_la1[64] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + case EQ: + case COMMA: + case DOT: + case RPARAN: + case COLON: + case INTERPOLATION: + case STRING: + case IDENT: + case NUMBER: + case FUNCTION: + ; + break; + default: + jj_la1[65] = jj_gen; + break label_44; + } + } + jj_consume_token(SEMICOLON); + label_45: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[66] = jj_gen; + break label_45; + } + jj_consume_token(S); + } + documentHandler.microsoftDirective(name, value); + } - /** - * @exception ParseException - * exception during the parse - */ - final public String simple_selector(String selector, char comb) - throws ParseException { - String simple_current = null; - String cond = null; +/** + * @exception ParseException exception during the parse + */ + final public String property() throws ParseException { + Token t;String s = ""; + label_46: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENT: + t = jj_consume_token(IDENT); + s += t.image; + break; + case INTERPOLATION: + t = jj_consume_token(INTERPOLATION); + s += t.image; + break; + default: + jj_la1[67] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + ; + break; + default: + jj_la1[68] = jj_gen; + break label_46; + } + } + label_47: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[69] = jj_gen; + break label_47; + } + jj_consume_token(S); + } + {if (true) return s;} + throw new Error("Missing return statement in function"); + } + + final public String variableName() throws ParseException { + Token n; + n = jj_consume_token(VARIABLE); + label_48: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[70] = jj_gen; + break label_48; + } + jj_consume_token(S); + } + {if (true) return convertIdent(n.image.substring(1));} + throw new Error("Missing return statement in function"); + } + + final public String functionName() throws ParseException { + Token n; + n = jj_consume_token(FUNCTION); + label_49: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[71] = jj_gen; + break label_49; + } + jj_consume_token(S); + } + {if (true) return convertIdent(n.image.substring(0, n.image.length()-1));} + throw new Error("Missing return statement in function"); + } - pseudoElt = null; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { +/** + * @exception ParseException exception during the parse + */ + final public void styleRule() throws ParseException { + boolean start = false; + ArrayList<String> l = null; + Token save; + Locator loc; + try { + l = selectorList(); + save = token; + jj_consume_token(LBRACE); + label_50: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[72] = jj_gen; + break label_50; + } + jj_consume_token(S); + } + start = true; + documentHandler.startSelector(l); + label_51: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: case ANY: case PARENT: + case DOT: + case COLON: case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case MICROSOFT_RULE: case IDENT: - simple_current = element_name(); - label_57: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACKET: - case DOT: - case COLON: - case HASH: - ; - break; - default: - jj_la1[80] = jj_gen; - break label_57; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case HASH: - cond = hash(cond); - break; - case DOT: - cond = _class(cond); - break; - case LBRACKET: - cond = attrib(cond); - break; - case COLON: - cond = pseudo(cond); - break; - default: - jj_la1[81] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - break; + case VARIABLE: + case HASH: + case IMPORT_SYM: + case MEDIA_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ; + break; + default: + jj_la1[73] = jj_gen; + break label_51; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: case LBRACKET: + case ANY: + case PARENT: case DOT: case COLON: + case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case IDENT: + case VARIABLE: case HASH: - label_58: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case HASH: - cond = hash(cond); - break; - case DOT: - cond = _class(cond); - break; - case LBRACKET: - cond = attrib(cond); - break; - case COLON: - cond = pseudo(cond); - break; - default: - jj_la1[82] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACKET: - case DOT: - case COLON: - case HASH: - ; - break; - default: - jj_la1[83] = jj_gen; - break label_58; - } - } - break; + case MEDIA_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ifContentStatement(); + break; + case MICROSOFT_RULE: + microsoftExtension(); + break; + case IMPORT_SYM: + importDeclaration(); + break; default: - jj_la1[84] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - if (simple_current == null) { - simple_current = ""; - } - if (cond != null) { - simple_current = simple_current + cond; - } - StringBuilder builder = new StringBuilder(); - switch (comb) { - case ' ': - if (selector != null) { - builder.append(selector).append(" "); - } - break; - case '+': - case '>': - case '~': - if (selector != null) { - builder.append(selector).append(" "); - } - builder.append(comb).append(" "); - break; - default: { - if (true) { - throw new ParseException("invalid state. send a bug report"); - } - } - } - builder.append(simple_current); - selector = builder.toString(); - - if (pseudoElt != null) { - selector = selector + pseudoElt; - } - { - if (true) { - return selector; - } + jj_la1[74] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + jj_consume_token(RBRACE); + label_52: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[75] = jj_gen; + break label_52; + } + jj_consume_token(S); + } + } catch (ThrowedParseException e) { + if (errorHandler != null) { + LocatorImpl li = new LocatorImpl(this, + e.e.currentToken.next.beginLine, + e.e.currentToken.next.beginColumn-1); + reportError(li, e.e); + } + } catch (ParseException e) { + reportError(getLocator(), e); + skipStatement(); + // reportWarningSkipText(getLocator(), skipStatement()); + + } catch (TokenMgrError e) { + reportWarningSkipText(getLocator(), skipStatement()); + } finally { + if (start) { + documentHandler.endSelector(); + } + } + } + + final public ArrayList<String> selectorList() throws ParseException { + ArrayList<String> selectors = new ArrayList<String>(); + String selector; + selector = selector(); + label_53: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[76] = jj_gen; + break label_53; + } + jj_consume_token(COMMA); + label_54: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[77] = jj_gen; + break label_54; } - throw new Error("Missing return statement in function"); + jj_consume_token(S); + } + selectors.add(selector); + selector = selector(); } + selectors.add(selector); + {if (true) return selectors;} + throw new Error("Missing return statement in function"); + } - /** - * @exception ParseException - * exception during the parse - */ - final public String _class(String pred) throws ParseException { - Token t; - String s = "."; - jj_consume_token(DOT); - label_59: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENT: - t = jj_consume_token(IDENT); - s += t.image; - break; - case INTERPOLATION: - t = jj_consume_token(INTERPOLATION); - s += t.image; - break; - default: - jj_la1[85] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - ; - break; - default: - jj_la1[86] = jj_gen; - break label_59; - } - } - if (pred == null) { - { - if (true) { - return s; - } - } +/** + * @exception ParseException exception during the parse + */ + final public String selector() throws ParseException { + String selector = null; + char comb; + try { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case IDENT: + case HASH: + selector = simple_selector(null, ' '); + break; + case PLUS: + case PRECEDES: + case SIBLING: + comb = combinatorChar(); + selector = simple_selector(selector, comb); + break; + default: + jj_la1[78] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + label_55: + while (true) { + if (jj_2_2(2)) { + ; } else { - { - if (true) { - return pred + s; - } - } - } - throw new Error("Missing return statement in function"); - } - - /** - * @exception ParseException - * exception during the parse - */ - final public String element_name() throws ParseException { - Token t; - String s = ""; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - label_60: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENT: - t = jj_consume_token(IDENT); - s += t.image; - break; - case INTERPOLATION: - t = jj_consume_token(INTERPOLATION); - s += t.image; - break; - default: - jj_la1[87] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - ; - break; - default: - jj_la1[88] = jj_gen; - break label_60; - } - } - { - if (true) { - return s; - } - } - break; - case ANY: - jj_consume_token(ANY); - { - if (true) { - return "*"; - } - } - break; - case PARENT: - jj_consume_token(PARENT); - { - if (true) { - return "&"; - } - } - break; + break label_55; + } + comb = combinator(); + selector = simple_selector(selector, comb); + } + label_56: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[89] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - throw new Error("Missing return statement in function"); + jj_la1[79] = jj_gen; + break label_56; + } + jj_consume_token(S); + } + {if (true) return selector;} + } catch (ParseException e) { + /* + Token t = getToken(1); + StringBuffer s = new StringBuffer(); + s.append(getToken(0).image); + while ((t.kind != COMMA) && (t.kind != SEMICOLON) + && (t.kind != LBRACE) && (t.kind != EOF)) { + s.append(t.image); + getNextToken(); + t = getToken(1); + } + reportWarningSkipText(getLocator(), s.toString()); + */ + Token t = getToken(1); + while ((t.kind != COMMA) && (t.kind != SEMICOLON) + && (t.kind != LBRACE) && (t.kind != EOF)) { + getNextToken(); + t = getToken(1); + } + + {if (true) throw new ThrowedParseException(e);} } + throw new Error("Missing return statement in function"); + } - /** - * @exception ParseException - * exception during the parse - */ - final public String attrib(String pred) throws ParseException { - int cases = 0; - Token att = null; - Token val = null; - String attValue = null; - jj_consume_token(LBRACKET); - label_61: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[90] = jj_gen; - break label_61; - } - jj_consume_token(S); +/** + * @exception ParseException exception during the parse + */ + final public String simple_selector(String selector, char comb) throws ParseException { + String simple_current = null; + String cond = null; + + pseudoElt = null; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ANY: + case PARENT: + case INTERPOLATION: + case IDENT: + simple_current = element_name(); + label_57: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LBRACKET: + case DOT: + case COLON: + case HASH: + ; + break; + default: + jj_la1[80] = jj_gen; + break label_57; } - att = jj_consume_token(IDENT); - label_62: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[91] = jj_gen; - break label_62; - } - jj_consume_token(S); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case HASH: + cond = hash(cond); + break; + case DOT: + cond = _class(cond); + break; + case LBRACKET: + cond = attrib(cond); + break; + case COLON: + cond = pseudo(cond); + break; + default: + jj_la1[81] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + break; + case LBRACKET: + case DOT: + case COLON: + case HASH: + label_58: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case HASH: + cond = hash(cond); + break; + case DOT: + cond = _class(cond); + break; + case LBRACKET: + cond = attrib(cond); + break; + case COLON: + cond = pseudo(cond); + break; + default: + jj_la1[82] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case DASHMATCH: - case CARETMATCH: - case DOLLARMATCH: - case STARMATCH: - case INCLUDES: - case EQ: - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case EQ: - jj_consume_token(EQ); - cases = 1; - break; - case INCLUDES: - jj_consume_token(INCLUDES); - cases = 2; - break; - case DASHMATCH: - jj_consume_token(DASHMATCH); - cases = 3; - break; - case CARETMATCH: - jj_consume_token(CARETMATCH); - cases = 4; - break; - case DOLLARMATCH: - jj_consume_token(DOLLARMATCH); - cases = 5; - break; - case STARMATCH: - jj_consume_token(STARMATCH); - cases = 6; - break; - default: - jj_la1[92] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - label_63: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LBRACKET: + case DOT: + case COLON: + case HASH: + ; + break; + default: + jj_la1[83] = jj_gen; + break label_58; + } + } + break; + default: + jj_la1[84] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + if (simple_current == null) { + simple_current = ""; + } + if (cond != null) { + simple_current = simple_current + cond; + } + StringBuilder builder = new StringBuilder(); + switch (comb) { + case ' ': + if(selector!=null){ + builder.append(selector).append(" "); + } break; - default: - jj_la1[93] = jj_gen; - break label_63; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENT: - val = jj_consume_token(IDENT); - attValue = val.image; - break; - case STRING: - val = jj_consume_token(STRING); - attValue = val.image; - break; - default: - jj_la1[94] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - label_64: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; + case '+': + case '>': + case '~': + if(selector!=null){ + builder.append(selector).append(" "); + } + builder.append(comb).append(" "); break; default: - jj_la1[95] = jj_gen; - break label_64; - } - jj_consume_token(S); - } - break; - default: - jj_la1[96] = jj_gen; - ; - } - jj_consume_token(RBRACKET); - String name = convertIdent(att.image); - String c; - switch (cases) { - case 0: - c = name; - break; - case 1: - c = name + "=" + attValue; - break; - case 2: - c = name + "~=" + attValue; - break; - case 3: - c = name + "|=" + attValue; - break; - case 4: - c = name + "^=" + attValue; - break; - case 5: - c = name + "$=" + attValue; - break; - case 6: - c = name + "*=" + attValue; - break; - default: - // never reached. - c = null; - } - c = "[" + c + "]"; - if (pred == null) { - { - if (true) { - return c; - } + {if (true) throw new ParseException("invalid state. send a bug report");} } - } else { - { - if (true) { - return pred + c; - } + builder.append(simple_current); + selector = builder.toString(); + + if (pseudoElt != null) { + selector = selector + pseudoElt; } - } - throw new Error("Missing return statement in function"); - } + {if (true) return selector;} + throw new Error("Missing return statement in function"); + } - /** - * @exception ParseException - * exception during the parse - */ - final public String pseudo(String pred) throws ParseException { - Token n; - Token param; - String d; - boolean isPseudoElement = false; - jj_consume_token(COLON); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COLON: - jj_consume_token(COLON); - isPseudoElement = true; - break; +/** + * @exception ParseException exception during the parse + */ + final public String _class(String pred) throws ParseException { + Token t; +String s = "."; + jj_consume_token(DOT); + label_59: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENT: + t = jj_consume_token(IDENT); + s += t.image; + break; + case INTERPOLATION: + t = jj_consume_token(INTERPOLATION); + s += t.image; + break; + default: + jj_la1[85] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + ; + break; + default: + jj_la1[86] = jj_gen; + break label_59; + } + } + if (pred == null) { + {if (true) return s;} + } else { + {if (true) return pred + s;} + } + throw new Error("Missing return statement in function"); + } + +/** + * @exception ParseException exception during the parse + */ + final public String element_name() throws ParseException { + Token t; String s = ""; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + label_60: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENT: + t = jj_consume_token(IDENT); + s += t.image; + break; + case INTERPOLATION: + t = jj_consume_token(INTERPOLATION); + s += t.image; + break; default: - jj_la1[97] = jj_gen; - ; + jj_la1[87] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: case IDENT: - n = jj_consume_token(IDENT); + ; + break; + default: + jj_la1[88] = jj_gen; + break label_60; + } + } + {if (true) return s;} + break; + case ANY: + jj_consume_token(ANY); + {if (true) return "*";} + break; + case PARENT: + jj_consume_token(PARENT); + {if (true) return "&";} + break; + default: + jj_la1[89] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + +/** + * @exception ParseException exception during the parse + */ + final public String attrib(String pred) throws ParseException { + int cases = 0; + Token att = null; + Token val = null; + String attValue = null; + jj_consume_token(LBRACKET); + label_61: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[90] = jj_gen; + break label_61; + } + jj_consume_token(S); + } + att = jj_consume_token(IDENT); + label_62: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[91] = jj_gen; + break label_62; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DASHMATCH: + case CARETMATCH: + case DOLLARMATCH: + case STARMATCH: + case INCLUDES: + case EQ: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case EQ: + jj_consume_token(EQ); + cases = 1; + break; + case INCLUDES: + jj_consume_token(INCLUDES); + cases = 2; + break; + case DASHMATCH: + jj_consume_token(DASHMATCH); + cases = 3; + break; + case CARETMATCH: + jj_consume_token(CARETMATCH); + cases = 4; + break; + case DOLLARMATCH: + jj_consume_token(DOLLARMATCH); + cases = 5; + break; + case STARMATCH: + jj_consume_token(STARMATCH); + cases = 6; + break; + default: + jj_la1[92] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + label_63: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[93] = jj_gen; + break label_63; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENT: + val = jj_consume_token(IDENT); + attValue = val.image; + break; + case STRING: + val = jj_consume_token(STRING); + attValue = val.image; + break; + default: + jj_la1[94] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + label_64: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[95] = jj_gen; + break label_64; + } + jj_consume_token(S); + } + break; + default: + jj_la1[96] = jj_gen; + ; + } + jj_consume_token(RBRACKET); + String name = convertIdent(att.image); + String c; + switch (cases) { + case 0: + c = name; + break; + case 1: + c = name + "=" + attValue; + break; + case 2: + c = name + "~=" + attValue; + break; + case 3: + c = name + "|=" +attValue; + break; + case 4: + c = name + "^=" +attValue; + break; + case 5: + c = name + "$=" +attValue; + break; + case 6: + c = name + "*=" +attValue; + break; + default: + // never reached. + c = null; + } + c = "[" + c + "]"; + if (pred == null) { + {if (true) return c;} + } else { + {if (true) return pred + c;} + } + throw new Error("Missing return statement in function"); + } + +/** + * @exception ParseException exception during the parse + */ + final public String pseudo(String pred) throws ParseException { + Token n; +Token param; +String d; +boolean isPseudoElement = false; + jj_consume_token(COLON); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COLON: + jj_consume_token(COLON); + isPseudoElement=true; + break; + default: + jj_la1[97] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENT: + n = jj_consume_token(IDENT); String s = ":" + convertIdent(n.image); if (isPseudoElement) { if (pseudoElt != null) { - { - if (true) { - throw new CSSParseException( - "duplicate pseudo element definition " + s, - getLocator()); - } - } + {if (true) throw new CSSParseException("duplicate pseudo element definition " + + s, getLocator());} } else { - pseudoElt = ":" + s; - { - if (true) { - return pred; - } - } + pseudoElt = ":"+s; + {if (true) return pred;} } } else { String c = s; if (pred == null) { - { - if (true) { - return c; - } - } + {if (true) return c;} } else { - { - if (true) { - return pred + c; - } - } - } - } - break; - case FUNCTION: - n = jj_consume_token(FUNCTION); - label_65: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[98] = jj_gen; - break label_65; + {if (true) return pred + c;} } - jj_consume_token(S); } - d = skipStatementUntilMatchingRightParan(); - jj_consume_token(RPARAN); - // accept anything between function and a right parenthesis - String f = convertIdent(n.image); - String colons = isPseudoElement ? "::" : ":"; - String pseudofn = colons + f + d + ")"; - if (pred == null) { - { - if (true) { - return pseudofn; - } - } - } else { - { - if (true) { - return pred + pseudofn; - } - } - } - break; + break; + case FUNCTION: + n = jj_consume_token(FUNCTION); + label_65: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[99] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - throw new Error("Missing return statement in function"); - } - - /** - * @exception ParseException - * exception during the parse - */ - final public String hash(String pred) throws ParseException { - Token n; - n = jj_consume_token(HASH); - String d = n.image; - if (pred == null) { - { - if (true) { - return d; - } - } - } else { - { - if (true) { - return pred + d; - } - } - } - throw new Error("Missing return statement in function"); - } + jj_la1[98] = jj_gen; + break label_65; + } + jj_consume_token(S); + } + d = skipStatementUntilMatchingRightParan(); + jj_consume_token(RPARAN); + // accept anything between function and a right parenthesis + String f = convertIdent(n.image); + String colons = isPseudoElement ? "::" : ":"; + String pseudofn = colons + f + d + ")"; + if (pred == null) { + {if (true) return pseudofn;} + } else { + {if (true) return pred + pseudofn;} + } + break; + default: + jj_la1[99] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } - final public void variable() throws ParseException { +/** + * @exception ParseException exception during the parse + */ + final public String hash(String pred) throws ParseException { + Token n; + n = jj_consume_token(HASH); + String d = n.image; + if (pred == null) { + {if (true) return d;} + } else { + {if (true) return pred + d;} + } + throw new Error("Missing return statement in function"); + } + + final public void variable() throws ParseException { String name; LexicalUnitImpl exp = null; boolean guarded = false; String raw; - try { - name = variableName(); - jj_consume_token(COLON); - label_66: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[100] = jj_gen; - break label_66; - } - jj_consume_token(S); - } - exp = expr(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case GUARDED_SYM: - guarded = guarded(); - break; - default: - jj_la1[101] = jj_gen; - ; - } - label_67: while (true) { - jj_consume_token(SEMICOLON); - label_68: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[102] = jj_gen; - break label_68; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - ; - break; - default: - jj_la1[103] = jj_gen; - break label_67; - } - } - documentHandler.variable(name, exp, guarded); - } catch (JumpException e) { + try { + name = variableName(); + jj_consume_token(COLON); + label_66: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[100] = jj_gen; + break label_66; + } + jj_consume_token(S); + } + exp = expr(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case GUARDED_SYM: + guarded = guarded(); + break; + default: + jj_la1[101] = jj_gen; + ; + } + label_67: + while (true) { + jj_consume_token(SEMICOLON); + label_68: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[102] = jj_gen; + break label_68; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + ; + break; + default: + jj_la1[103] = jj_gen; + break label_67; + } + } + exp = replaceNullValues(exp); + documentHandler.variable(name, exp, guarded); + } catch (JumpException e) { skipAfterExpression(); - } catch (NumberFormatException e) { + } catch (NumberFormatException e) { if (errorHandler != null) { errorHandler.error(new CSSParseException("Invalid number " - + e.getMessage(), getLocator(), e)); + + e.getMessage(), + getLocator(), + e)); } reportWarningSkipText(getLocator(), skipAfterExpression()); - } catch (ParseException e) { + } catch (ParseException e) { if (errorHandler != null) { if (e.currentToken != null) { - LocatorImpl li = new LocatorImpl(this, - e.currentToken.next.beginLine, - e.currentToken.next.beginColumn - 1); - reportError(li, e); + LocatorImpl li = new LocatorImpl(this, + e.currentToken.next.beginLine, + e.currentToken.next.beginColumn-1); + reportError(li, e); } else { - reportError(getLocator(), e); - } + reportError(getLocator(), e); + } skipAfterExpression(); } else { skipAfterExpression(); } - } } + } - final public void controlDirective() throws ParseException { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IF_SYM: - ifDirective(); - break; + LexicalUnitImpl replaceNullValues(LexicalUnitImpl unit) throws ParseException { + if(unit == null){ + return null; + } + if (unit.getNextLexicalUnit() != null) { + unit.setNextLexicalUnit(replaceNullValues(unit.getNextLexicalUnit())); + } + if (unit.getLexicalUnitType() == SCSSLexicalUnit.SAC_IDENT + && "null".equals(unit.getStringValue())) { + LexicalUnitImpl next = unit.getNextLexicalUnit(); + unit = LexicalUnitImpl.createNull(unit.getLineNumber(), unit.getColumnNumber(), + unit.getPreviousLexicalUnit()); + unit.setNextLexicalUnit(next); + } + return unit; + } + + final public void controlDirective() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IF_SYM: + ifDirective(); + break; + case EACH_SYM: + eachDirective(); + break; + default: + jj_la1[104] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void ifContentStatement() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case CONTENT_SYM: + contentDirective(); + break; + case INCLUDE_SYM: + includeDirective(); + break; + case MEDIA_SYM: + media(); + break; + case EXTEND_SYM: + extendDirective(); + break; + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case DEBUG_SYM: + case WARN_SYM: + case IDENT: + case HASH: + styleRuleOrDeclarationOrNestedProperties(); + break; + case KEY_FRAME_SYM: + keyframes(); + break; + default: + jj_la1[105] = jj_gen; + if (jj_2_3(2147483647)) { + variable(); + } else { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case VARIABLE: + listModifyDirective(); + break; case EACH_SYM: - eachDirective(); - break; + case IF_SYM: + controlDirective(); + break; + case ATKEYWORD: + atRuleDeclaration(); + break; default: - jj_la1[104] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - - final public void ifContentStatement() throws ParseException { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CONTENT_SYM: - contentDirective(); - break; - case INCLUDE_SYM: - includeDirective(); - break; - case MEDIA_SYM: - media(); - break; - case EXTEND_SYM: - extendDirective(); - break; + jj_la1[106] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } + + final public void ifDirective() throws ParseException { + Token n = null; + String s = null; + String evaluator = ""; + jj_consume_token(IF_SYM); + label_69: + while (true) { + s = booleanExpressionToken(); + evaluator += s; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + case EQ: + case PLUS: + case MINUS: + case PRECEDES: + case SUCCEEDS: + case DIV: + case ANY: + case LPARAN: + case RPARAN: + case COMPARE: + case OR: + case AND: + case NOT_EQ: + case IDENT: + case NUMBER: + case VARIABLE: + case CONTAINS: + ; + break; + default: + jj_la1[107] = jj_gen; + break label_69; + } + } + jj_consume_token(LBRACE); + label_70: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[108] = jj_gen; + break label_70; + } + jj_consume_token(S); + } + documentHandler.startIfElseDirective(); + documentHandler.ifDirective(evaluator); + label_71: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case IDENT: + case VARIABLE: + case HASH: + case MEDIA_SYM: + case FONT_FACE_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ; + break; + default: + jj_la1[109] = jj_gen; + break label_71; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case IDENT: + case VARIABLE: + case HASH: + case MEDIA_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ifContentStatement(); + break; + case FONT_FACE_SYM: + fontFace(); + break; + default: + jj_la1[110] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + jj_consume_token(RBRACE); + label_72: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[111] = jj_gen; + break label_72; + } + jj_consume_token(S); + } + label_73: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case ELSE_SYM: + ; + break; + default: + jj_la1[112] = jj_gen; + break label_73; + } + elseDirective(); + } + documentHandler.endIfElseDirective(); + } + + final public void elseDirective() throws ParseException { + String evaluator = ""; + Token n = null; + String s = null; + jj_consume_token(ELSE_SYM); + label_74: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[113] = jj_gen; + break label_74; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IF: + jj_consume_token(IF); + label_75: + while (true) { + s = booleanExpressionToken(); + evaluator += s; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + case EQ: case PLUS: + case MINUS: case PRECEDES: - case SIBLING: - case LBRACKET: + case SUCCEEDS: + case DIV: case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case DEBUG_SYM: - case WARN_SYM: - case IDENT: - case HASH: - styleRuleOrDeclarationOrNestedProperties(); - break; - case KEY_FRAME_SYM: - keyframes(); - break; - default: - jj_la1[105] = jj_gen; - if (jj_2_3(2147483647)) { - variable(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case VARIABLE: - listModifyDirective(); - break; - case EACH_SYM: - case IF_SYM: - controlDirective(); - break; - case ATKEYWORD: - atRuleDeclaration(); - break; - default: - jj_la1[106] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - } - } - - final public void ifDirective() throws ParseException { - Token n = null; - String s = null; - String evaluator = ""; - jj_consume_token(IF_SYM); - label_69: while (true) { - s = booleanExpressionToken(); - evaluator += s; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - case EQ: - case PLUS: - case MINUS: - case PRECEDES: - case SUCCEEDS: - case DIV: - case ANY: - case LPARAN: - case RPARAN: - case COMPARE: - case OR: - case AND: - case NOT_EQ: - case IDENT: - case NUMBER: - case VARIABLE: - case CONTAINS: - ; - break; - default: - jj_la1[107] = jj_gen; - break label_69; - } - } - jj_consume_token(LBRACE); - label_70: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[108] = jj_gen; - break label_70; - } - jj_consume_token(S); - } - documentHandler.startIfElseDirective(); - documentHandler.ifDirective(evaluator); - label_71: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case IDENT: - case VARIABLE: - case HASH: - case MEDIA_SYM: - case FONT_FACE_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ; - break; - default: - jj_la1[109] = jj_gen; - break label_71; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case IDENT: - case VARIABLE: - case HASH: - case MEDIA_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ifContentStatement(); - break; - case FONT_FACE_SYM: - fontFace(); - break; - default: - jj_la1[110] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - jj_consume_token(RBRACE); - label_72: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[111] = jj_gen; - break label_72; - } - jj_consume_token(S); - } - label_73: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ELSE_SYM: - ; - break; - default: - jj_la1[112] = jj_gen; - break label_73; - } - elseDirective(); - } - documentHandler.endIfElseDirective(); - } - - final public void elseDirective() throws ParseException { - String evaluator = ""; - Token n = null; - String s = null; - jj_consume_token(ELSE_SYM); - label_74: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[113] = jj_gen; - break label_74; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IF: - jj_consume_token(IF); - label_75: while (true) { - s = booleanExpressionToken(); - evaluator += s; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - case EQ: - case PLUS: - case MINUS: - case PRECEDES: - case SUCCEEDS: - case DIV: - case ANY: - case LPARAN: - case RPARAN: - case COMPARE: - case OR: - case AND: - case NOT_EQ: - case IDENT: - case NUMBER: - case VARIABLE: - case CONTAINS: - ; - break; - default: - jj_la1[114] = jj_gen; - break label_75; - } - } - break; - default: - jj_la1[115] = jj_gen; - ; - } - jj_consume_token(LBRACE); - label_76: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[116] = jj_gen; - break label_76; - } - jj_consume_token(S); - } - if (!evaluator.trim().equals("")) { - documentHandler.ifDirective(evaluator); - } else { - documentHandler.elseDirective(); - } - label_77: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case IDENT: - case VARIABLE: - case HASH: - case MEDIA_SYM: - case FONT_FACE_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ; - break; - default: - jj_la1[117] = jj_gen; - break label_77; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case IDENT: - case VARIABLE: - case HASH: - case MEDIA_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ifContentStatement(); - break; - case FONT_FACE_SYM: - fontFace(); - break; - default: - jj_la1[118] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - jj_consume_token(RBRACE); - label_78: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[119] = jj_gen; - break label_78; - } - jj_consume_token(S); - } - } - - final public String booleanExpressionToken() throws ParseException { - Token n = null; - String s = null; - if (jj_2_4(2147483647)) { - s = containsDirective(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case VARIABLE: - n = jj_consume_token(VARIABLE); - break; - case IDENT: - n = jj_consume_token(IDENT); - break; - case NUMBER: - n = jj_consume_token(NUMBER); - break; - case LPARAN: - n = jj_consume_token(LPARAN); - break; - case RPARAN: - n = jj_consume_token(RPARAN); - break; - case PLUS: - n = jj_consume_token(PLUS); - break; - case MINUS: - n = jj_consume_token(MINUS); - break; - case DIV: - n = jj_consume_token(DIV); - break; - case ANY: - n = jj_consume_token(ANY); - break; - case COMPARE: - n = jj_consume_token(COMPARE); - break; - case EQ: - n = jj_consume_token(EQ); - break; - case PRECEDES: - n = jj_consume_token(PRECEDES); - break; - case SUCCEEDS: - n = jj_consume_token(SUCCEEDS); - break; - case OR: - n = jj_consume_token(OR); - break; - case AND: - n = jj_consume_token(AND); - break; - case S: - n = jj_consume_token(S); - break; - case NOT_EQ: - n = jj_consume_token(NOT_EQ); - break; - default: - jj_la1[120] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - if (n != null) { - { - if (true) { - return n.image; - } - } - } else { - { - if (true) { - return s; - } - } - } - throw new Error("Missing return statement in function"); - } - - final public void eachDirective() throws ParseException { - Token var; - ArrayList<String> list = null; - String listVariable = null; - jj_consume_token(EACH_SYM); - label_79: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[121] = jj_gen; - break label_79; - } - jj_consume_token(S); - } - var = jj_consume_token(VARIABLE); - label_80: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[122] = jj_gen; - break label_80; - } - jj_consume_token(S); - } - jj_consume_token(EACH_IN); - label_81: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[123] = jj_gen; - break label_81; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LPARAN: + case RPARAN: + case COMPARE: + case OR: + case AND: + case NOT_EQ: case IDENT: - list = stringList(); - documentHandler.startEachDirective(var.image, list); - break; + case NUMBER: case VARIABLE: - listVariable = variableName(); - documentHandler.startEachDirective(var.image, listVariable); - break; + case CONTAINS: + ; + break; default: - jj_la1[124] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - jj_consume_token(LBRACE); - label_82: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[125] = jj_gen; - break label_82; - } - jj_consume_token(S); - } - label_83: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case IDENT: - case VARIABLE: - case HASH: - case MEDIA_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ; - break; - default: - jj_la1[126] = jj_gen; - break label_83; - } - ifContentStatement(); - } - jj_consume_token(RBRACE); - label_84: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[127] = jj_gen; - break label_84; - } - jj_consume_token(S); - } - documentHandler.endEachDirective(); - } - - final public ArrayList<String> stringList() throws ParseException { - ArrayList<String> strings = new ArrayList<String>(); + jj_la1[114] = jj_gen; + break label_75; + } + } + break; + default: + jj_la1[115] = jj_gen; + ; + } + jj_consume_token(LBRACE); + label_76: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[116] = jj_gen; + break label_76; + } + jj_consume_token(S); + } + if(!evaluator.trim().equals("")){ documentHandler.ifDirective(evaluator); } + else{ documentHandler.elseDirective(); } + label_77: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case IDENT: + case VARIABLE: + case HASH: + case MEDIA_SYM: + case FONT_FACE_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ; + break; + default: + jj_la1[117] = jj_gen; + break label_77; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case IDENT: + case VARIABLE: + case HASH: + case MEDIA_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ifContentStatement(); + break; + case FONT_FACE_SYM: + fontFace(); + break; + default: + jj_la1[118] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + jj_consume_token(RBRACE); + label_78: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[119] = jj_gen; + break label_78; + } + jj_consume_token(S); + } + } + + final public String booleanExpressionToken() throws ParseException { + Token n = null; + String s = null; + if (jj_2_4(2147483647)) { + s = containsDirective(); + } else { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case VARIABLE: + n = jj_consume_token(VARIABLE); + break; + case IDENT: + n = jj_consume_token(IDENT); + break; + case NUMBER: + n = jj_consume_token(NUMBER); + break; + case LPARAN: + n = jj_consume_token(LPARAN); + break; + case RPARAN: + n = jj_consume_token(RPARAN); + break; + case PLUS: + n = jj_consume_token(PLUS); + break; + case MINUS: + n = jj_consume_token(MINUS); + break; + case DIV: + n = jj_consume_token(DIV); + break; + case ANY: + n = jj_consume_token(ANY); + break; + case COMPARE: + n = jj_consume_token(COMPARE); + break; + case EQ: + n = jj_consume_token(EQ); + break; + case PRECEDES: + n = jj_consume_token(PRECEDES); + break; + case SUCCEEDS: + n = jj_consume_token(SUCCEEDS); + break; + case OR: + n = jj_consume_token(OR); + break; + case AND: + n = jj_consume_token(AND); + break; + case S: + n = jj_consume_token(S); + break; + case NOT_EQ: + n = jj_consume_token(NOT_EQ); + break; + default: + jj_la1[120] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + if(n!=null){{if (true) return n.image;}} + else{{if (true) return s;}} + throw new Error("Missing return statement in function"); + } + + final public void eachDirective() throws ParseException { + Token var; + ArrayList<String> list = null; + String listVariable = null; + jj_consume_token(EACH_SYM); + label_79: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[121] = jj_gen; + break label_79; + } + jj_consume_token(S); + } + var = jj_consume_token(VARIABLE); + label_80: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[122] = jj_gen; + break label_80; + } + jj_consume_token(S); + } + jj_consume_token(EACH_IN); + label_81: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[123] = jj_gen; + break label_81; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENT: + list = stringList(); + documentHandler.startEachDirective(var.image, list); + break; + case VARIABLE: + listVariable = variableName(); + documentHandler.startEachDirective(var.image, listVariable); + break; + default: + jj_la1[124] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(LBRACE); + label_82: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[125] = jj_gen; + break label_82; + } + jj_consume_token(S); + } + label_83: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case IDENT: + case VARIABLE: + case HASH: + case MEDIA_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ; + break; + default: + jj_la1[126] = jj_gen; + break label_83; + } + ifContentStatement(); + } + jj_consume_token(RBRACE); + label_84: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[127] = jj_gen; + break label_84; + } + jj_consume_token(S); + } + documentHandler.endEachDirective(); + } + + final public ArrayList<String > stringList() throws ParseException { + ArrayList<String > strings = new ArrayList<String >(); Token input; - input = jj_consume_token(IDENT); - label_85: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[128] = jj_gen; - break label_85; - } - jj_consume_token(S); - } - strings.add(input.image); - label_86: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - jj_la1[129] = jj_gen; - break label_86; - } - jj_consume_token(COMMA); - label_87: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[130] = jj_gen; - break label_87; - } - jj_consume_token(S); - } - input = jj_consume_token(IDENT); - strings.add(input.image); - label_88: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[131] = jj_gen; - break label_88; - } - jj_consume_token(S); - } - } - { - if (true) { - return strings; - } - } - throw new Error("Missing return statement in function"); - } - - final public void mixinDirective() throws ParseException { - String name; - ArrayList<VariableNode> args = null; - String body; - jj_consume_token(MIXIN_SYM); - label_89: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[132] = jj_gen; - break label_89; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - name = property(); - break; - case FUNCTION: - name = functionName(); - args = arglist(); - jj_consume_token(RPARAN); - label_90: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[133] = jj_gen; - break label_90; - } - jj_consume_token(S); - } - break; + input = jj_consume_token(IDENT); + label_85: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[128] = jj_gen; + break label_85; + } + jj_consume_token(S); + } + strings.add(input.image); + label_86: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[129] = jj_gen; + break label_86; + } + jj_consume_token(COMMA); + label_87: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[134] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - jj_consume_token(LBRACE); - label_91: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[135] = jj_gen; - break label_91; - } - jj_consume_token(S); - } - documentHandler.startMixinDirective(name, args); - label_92: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case IDENT: - case VARIABLE: - case HASH: - case MEDIA_SYM: - case PAGE_SYM: - case FONT_FACE_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ; - break; - default: - jj_la1[136] = jj_gen; - break label_92; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case INCLUDE_SYM: - case DEBUG_SYM: - case WARN_SYM: - case EACH_SYM: - case IF_SYM: - case EXTEND_SYM: - case CONTENT_SYM: - case IDENT: - case VARIABLE: - case HASH: - case MEDIA_SYM: - case KEY_FRAME_SYM: - case ATKEYWORD: - ifContentStatement(); - break; - case FONT_FACE_SYM: - fontFace(); - break; - case PAGE_SYM: - page(); - break; - default: - jj_la1[137] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } + jj_la1[130] = jj_gen; + break label_87; + } + jj_consume_token(S); + } + input = jj_consume_token(IDENT); + strings.add(input.image); + label_88: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[131] = jj_gen; + break label_88; + } + jj_consume_token(S); + } + } + {if (true) return strings;} + throw new Error("Missing return statement in function"); + } + + final public void mixinDirective() throws ParseException { + String name; + ArrayList<VariableNode> args = null; + String body; + jj_consume_token(MIXIN_SYM); + label_89: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[132] = jj_gen; + break label_89; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + name = property(); + break; + case FUNCTION: + name = functionName(); + args = arglist(); + jj_consume_token(RPARAN); + label_90: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[133] = jj_gen; + break label_90; + } + jj_consume_token(S); + } + break; + default: + jj_la1[134] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(LBRACE); + label_91: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[135] = jj_gen; + break label_91; + } + jj_consume_token(S); + } + documentHandler.startMixinDirective(name, args); + label_92: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case IDENT: + case VARIABLE: + case HASH: + case MEDIA_SYM: + case PAGE_SYM: + case FONT_FACE_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ; + break; + default: + jj_la1[136] = jj_gen; + break label_92; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case INCLUDE_SYM: + case DEBUG_SYM: + case WARN_SYM: + case EACH_SYM: + case IF_SYM: + case EXTEND_SYM: + case CONTENT_SYM: + case IDENT: + case VARIABLE: + case HASH: + case MEDIA_SYM: + case KEY_FRAME_SYM: + case ATKEYWORD: + ifContentStatement(); + break; + case FONT_FACE_SYM: + fontFace(); + break; + case PAGE_SYM: + page(); + break; + default: + jj_la1[137] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + jj_consume_token(RBRACE); + label_93: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[138] = jj_gen; + break label_93; + } + jj_consume_token(S); + } + documentHandler.endMixinDirective(name, args); + } + + final public ArrayList<VariableNode> arglist() throws ParseException { + ArrayList<VariableNode> args = new ArrayList<VariableNode>(); + VariableNode arg; + boolean hasNonOptionalArgument = false; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case VARIABLE: + arg = mixinArg(); + label_94: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[139] = jj_gen; + break label_94; } - jj_consume_token(RBRACE); - label_93: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[138] = jj_gen; - break label_93; - } - jj_consume_token(S); + jj_consume_token(COMMA); + label_95: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[140] = jj_gen; + break label_95; + } + jj_consume_token(S); } - documentHandler.endMixinDirective(name, args); - } - - final public ArrayList<VariableNode> arglist() throws ParseException { - ArrayList<VariableNode> args = new ArrayList<VariableNode>(); - VariableNode arg; - boolean hasNonOptionalArgument = false; + hasNonOptionalArgument = checkMixinForNonOptionalArguments(arg, hasNonOptionalArgument); args.add(arg); arg = mixinArg(); - label_94: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - jj_la1[139] = jj_gen; - break label_94; - } - jj_consume_token(COMMA); - label_95: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[140] = jj_gen; - break label_95; - } - jj_consume_token(S); - } - hasNonOptionalArgument = checkMixinForNonOptionalArguments(arg, - hasNonOptionalArgument); - args.add(arg); - arg = mixinArg(); - } - hasNonOptionalArgument = checkMixinForNonOptionalArguments(arg, - hasNonOptionalArgument); - args.add(arg); - { - if (true) { - return args; - } - } - throw new Error("Missing return statement in function"); + } + hasNonOptionalArgument = checkMixinForNonOptionalArguments(arg, hasNonOptionalArgument); args.add(arg); + break; + default: + jj_la1[141] = jj_gen; + ; } + {if (true) return args;} + throw new Error("Missing return statement in function"); + } - boolean checkMixinForNonOptionalArguments(VariableNode arg, - boolean hasNonOptionalArguments) throws ParseException { - boolean currentArgHasArguments = arg.getExpr() != null - && arg.getExpr().getLexicalUnitType() == LexicalUnitImpl.SCSS_VARIABLE - && arg.getExpr().getNextLexicalUnit() != null; + boolean checkMixinForNonOptionalArguments(VariableNode arg, boolean hasNonOptionalArguments) throws ParseException { + boolean currentArgHasArguments = arg.getExpr() != null && arg.getExpr().getLexicalUnitType() == LexicalUnitImpl.SCSS_VARIABLE && arg.getExpr().getNextLexicalUnit() != null; - if (currentArgHasArguments) { - if (hasNonOptionalArguments) { - throw new ParseException("Sass Error: Required argument $" - + arg.getName() - + " must come before any optional arguments."); - } - return hasNonOptionalArguments; - } else { - return true; - } - } - - final public VariableNode mixinArg() throws ParseException { - String name; - Token variable = null; - LexicalUnitImpl first = null; - LexicalUnitImpl prev = null; - LexicalUnitImpl next = null; - name = variableName(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COLON: - case VARIABLE: - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COLON: - jj_consume_token(COLON); - label_96: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[141] = jj_gen; - break label_96; - } - jj_consume_token(S); - } - first = nonVariableTerm(null); - prev = first; - label_97: while (true) { - if (jj_2_5(3)) { - ; - } else { - break label_97; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - jj_consume_token(COMMA); - label_98: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[142] = jj_gen; - break label_98; - } - jj_consume_token(S); - } - break; - default: - jj_la1[143] = jj_gen; - ; - } - prev = nonVariableTerm(prev); + if(currentArgHasArguments) + { + if(hasNonOptionalArguments) + { + throw new ParseException("Sass Error: Required argument $"+ arg.getName() +" must come before any optional arguments."); } - break; - case VARIABLE: - variable = jj_consume_token(VARIABLE); - first = LexicalUnitImpl.createVariable(token.beginLine, - token.beginColumn, prev, variable.image); - break; - default: - jj_la1[144] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - break; - default: - jj_la1[145] = jj_gen; - ; - } - VariableNode arg = new VariableNode(name, first, false); + return hasNonOptionalArguments; + }else { - if (true) { - return arg; - } + return true; + } + } + + final public VariableNode mixinArg() throws ParseException { + String name; + Token variable = null; + LexicalUnitImpl first = null; + LexicalUnitImpl prev = null; + LexicalUnitImpl next = null; + name = variableName(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COLON: + case VARIABLE: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COLON: + jj_consume_token(COLON); + label_96: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[142] = jj_gen; + break label_96; + } + jj_consume_token(S); } - throw new Error("Missing return statement in function"); - } - - final public ArrayList<LexicalUnitImpl> argValuelist() - throws ParseException { - ArrayList<LexicalUnitImpl> args = new ArrayList<LexicalUnitImpl>(); - LexicalUnitImpl first = null; - LexicalUnitImpl next = null; - LexicalUnitImpl prev = null; - first = term(null); - args.add(first); + first = nonVariableTerm(null); prev = first; - label_99: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case MINUS: - case DOT: - case COLON: - case TO: - case THROUGH: - case FROM: - case STRING: - case IDENT: - case NUMBER: - case URL: - case VARIABLE: - case PERCENTAGE: - case PT: - case MM: - case CM: - case PC: - case IN: - case PX: - case EMS: - case LEM: - case REM: - case EXS: - case DEG: - case RAD: - case GRAD: - case MS: - case SECOND: - case HZ: - case KHZ: - case DIMEN: - case HASH: - case UNICODERANGE: - case FUNCTION: - ; - break; - default: - jj_la1[146] = jj_gen; - break label_99; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COLON: - jj_consume_token(COLON); - label_100: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[147] = jj_gen; - break label_100; - } - jj_consume_token(S); - } - break; - default: - jj_la1[148] = jj_gen; - ; - } - next = term(prev); - prev.setNextLexicalUnit(next); - prev = next; - } - label_101: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - jj_la1[149] = jj_gen; - break label_101; - } + label_97: + while (true) { + if (jj_2_5(3)) { + ; + } else { + break label_97; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: jj_consume_token(COMMA); - label_102: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[150] = jj_gen; - break label_102; - } - jj_consume_token(S); - } - first = term(null); - args.add(first); - prev = first; - label_103: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case MINUS: - case DOT: - case COLON: - case TO: - case THROUGH: - case FROM: - case STRING: - case IDENT: - case NUMBER: - case URL: - case VARIABLE: - case PERCENTAGE: - case PT: - case MM: - case CM: - case PC: - case IN: - case PX: - case EMS: - case LEM: - case REM: - case EXS: - case DEG: - case RAD: - case GRAD: - case MS: - case SECOND: - case HZ: - case KHZ: - case DIMEN: - case HASH: - case UNICODERANGE: - case FUNCTION: - ; - break; - default: - jj_la1[151] = jj_gen; - break label_103; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COLON: - jj_consume_token(COLON); - label_104: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[152] = jj_gen; - break label_104; - } - jj_consume_token(S); - } - break; - default: - jj_la1[153] = jj_gen; - ; - } - next = term(prev); - prev.setNextLexicalUnit(next); - prev = next; - } - } - { - if (true) { - return args; - } - } - throw new Error("Missing return statement in function"); - } - - final public void includeDirective() throws ParseException { - String name; - ArrayList<LexicalUnitImpl> args = null; - jj_consume_token(INCLUDE_SYM); - label_105: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: + label_98: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: ; break; - default: - jj_la1[154] = jj_gen; - break label_105; + default: + jj_la1[143] = jj_gen; + break label_98; + } + jj_consume_token(S); } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - name = property(); break; + default: + jj_la1[144] = jj_gen; + ; + } + prev = nonVariableTerm(prev); + } + break; + case VARIABLE: + variable = jj_consume_token(VARIABLE); + first = LexicalUnitImpl.createVariable(token.beginLine, token.beginColumn, + prev, variable.image); + break; + default: + jj_la1[145] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_la1[146] = jj_gen; + ; + } + VariableNode arg = new VariableNode(name, first, false); + {if (true) return arg;} + throw new Error("Missing return statement in function"); + } + + final public ArrayList<LexicalUnitImpl> argValuelist() throws ParseException { + ArrayList<LexicalUnitImpl> args = new ArrayList<LexicalUnitImpl>(); + LexicalUnitImpl first = null; + LexicalUnitImpl next = null; + LexicalUnitImpl prev = null; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case MINUS: + case DOT: + case TO: + case THROUGH: + case FROM: + case STRING: + case IDENT: + case NUMBER: + case URL: + case VARIABLE: + case PERCENTAGE: + case PT: + case MM: + case CM: + case PC: + case IN: + case PX: + case EMS: + case LEM: + case REM: + case EXS: + case DEG: + case RAD: + case GRAD: + case MS: + case SECOND: + case HZ: + case KHZ: + case DIMEN: + case HASH: + case UNICODERANGE: + case FUNCTION: + first = term(null); + args.add(first); prev = first; + label_99: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case MINUS: + case DOT: + case COLON: + case TO: + case THROUGH: + case FROM: + case STRING: + case IDENT: + case NUMBER: + case URL: case VARIABLE: - name = variableName(); - name = "$" + name; - break; + case PERCENTAGE: + case PT: + case MM: + case CM: + case PC: + case IN: + case PX: + case EMS: + case LEM: + case REM: + case EXS: + case DEG: + case RAD: + case GRAD: + case MS: + case SECOND: + case HZ: + case KHZ: + case DIMEN: + case HASH: + case UNICODERANGE: case FUNCTION: - name = functionName(); - args = argValuelist(); - jj_consume_token(RPARAN); - label_106: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[155] = jj_gen; - break label_106; - } - jj_consume_token(S); - } - break; + ; + break; default: - jj_la1[156] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); + jj_la1[147] = jj_gen; + break label_99; } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - label_107: while (true) { - jj_consume_token(SEMICOLON); - label_108: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[157] = jj_gen; - break label_108; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - ; - break; - default: - jj_la1[158] = jj_gen; - break label_107; - } - } - documentHandler.includeDirective(name, args); - break; - case LBRACE: - jj_consume_token(LBRACE); - label_109: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[159] = jj_gen; - break label_109; - } - jj_consume_token(S); - } - documentHandler.startIncludeContentBlock(name, args); - label_110: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case TO: - case FROM: - case DEBUG_SYM: - case WARN_SYM: - case IDENT: - case PERCENTAGE: - case HASH: - ; - break; - default: - jj_la1[160] = jj_gen; - break label_110; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case DEBUG_SYM: - case WARN_SYM: - case IDENT: - case HASH: - styleRuleOrDeclarationOrNestedProperties(); - break; - case TO: - case FROM: - case PERCENTAGE: - keyframeSelector(); - break; - default: - jj_la1[161] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - jj_consume_token(RBRACE); - label_111: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[162] = jj_gen; - break label_111; - } - jj_consume_token(S); - } - documentHandler.endIncludeContentBlock(); - break; - default: - jj_la1[163] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - - final public String interpolation() throws ParseException { - Token n; - n = jj_consume_token(INTERPOLATION); - { - if (true) { - return n.image; - } - } - throw new Error("Missing return statement in function"); - } - - final public void listModifyDirective() throws ParseException { - String list = null; - String remove = null; - String separator = null; - String variable = null; - Token n = null; - Token type = null; - // refactor, remove those 3 LOOKAHEAD(5). - n = jj_consume_token(VARIABLE); - variable = n.image; - label_112: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COLON: + jj_consume_token(COLON); + label_100: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case S: - ; - break; + ; + break; default: - jj_la1[164] = jj_gen; - break label_112; + jj_la1[148] = jj_gen; + break label_100; } jj_consume_token(S); - } - jj_consume_token(COLON); - label_113: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[165] = jj_gen; - break label_113; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case APPEND: - type = jj_consume_token(APPEND); - break; - case REMOVE: - type = jj_consume_token(REMOVE); - break; - case CONTAINS: - type = jj_consume_token(CONTAINS); - break; + } + break; default: - jj_la1[166] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - label_114: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[167] = jj_gen; - break label_114; - } - jj_consume_token(S); - } - list = listModifyDirectiveArgs(0); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case RPARAN: - jj_consume_token(RPARAN); - break; + jj_la1[149] = jj_gen; + ; + } + next = term(prev); + prev.setNextLexicalUnit(next); prev = next; + } + label_101: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; default: - jj_la1[168] = jj_gen; - ; + jj_la1[150] = jj_gen; + break label_101; } jj_consume_token(COMMA); - label_115: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[169] = jj_gen; - break label_115; - } - jj_consume_token(S); - } - remove = listModifyDirectiveArgs(1); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - jj_consume_token(COMMA); - label_116: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[170] = jj_gen; - break label_116; - } - jj_consume_token(S); - } - n = jj_consume_token(IDENT); - separator = n.image; - label_117: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[171] = jj_gen; - break label_117; - } - jj_consume_token(S); - } - break; - default: - jj_la1[172] = jj_gen; + label_102: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: ; - } - jj_consume_token(RPARAN); - switch (type.kind) { - case APPEND: - documentHandler.appendDirective(variable, list, remove, separator); - break; - case REMOVE: - documentHandler.removeDirective(variable, list, remove, separator); - break; - case CONTAINS: - if (variable == null) { - variable = "$var_" + UUID.randomUUID(); - } - documentHandler - .containsDirective(variable, list, remove, separator); - break; - default: break; + default: + jj_la1[151] = jj_gen; + break label_102; + } + jj_consume_token(S); } - label_118: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: + first = term(null); + args.add(first); prev = first; + label_103: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case MINUS: + case DOT: + case COLON: + case TO: + case THROUGH: + case FROM: + case STRING: + case IDENT: + case NUMBER: + case URL: + case VARIABLE: + case PERCENTAGE: + case PT: + case MM: + case CM: + case PC: + case IN: + case PX: + case EMS: + case LEM: + case REM: + case EXS: + case DEG: + case RAD: + case GRAD: + case MS: + case SECOND: + case HZ: + case KHZ: + case DIMEN: + case HASH: + case UNICODERANGE: + case FUNCTION: + ; + break; + default: + jj_la1[152] = jj_gen; + break label_103; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COLON: + jj_consume_token(COLON); + label_104: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: ; break; - default: - jj_la1[173] = jj_gen; - break label_118; + default: + jj_la1[153] = jj_gen; + break label_104; + } + jj_consume_token(S); } - jj_consume_token(S); - } + break; + default: + jj_la1[154] = jj_gen; + ; + } + next = term(prev); + prev.setNextLexicalUnit(next); prev = next; + } + } + break; + default: + jj_la1[155] = jj_gen; + ; + } + {if (true) return args;} + throw new Error("Missing return statement in function"); + } + + final public void includeDirective() throws ParseException { + String name; + ArrayList<LexicalUnitImpl> args=null; + jj_consume_token(INCLUDE_SYM); + label_105: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[156] = jj_gen; + break label_105; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + name = property(); + break; + case VARIABLE: + name = variableName(); + name = "$"+name; + break; + case FUNCTION: + name = functionName(); + args = argValuelist(); + jj_consume_token(RPARAN); + label_106: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[157] = jj_gen; + break label_106; + } + jj_consume_token(S); + } + break; + default: + jj_la1[158] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + documentHandler.startInclude(name, args); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LBRACE: + includeDirectiveBlockContents(); + break; + case SEMICOLON: + includeDirectiveTerminator(); + break; + default: + jj_la1[159] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + documentHandler.endInclude(); + } + + final public void includeDirectiveTerminator() throws ParseException { + try { + label_107: + while (true) { jj_consume_token(SEMICOLON); - label_119: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[174] = jj_gen; - break label_119; - } - jj_consume_token(S); + label_108: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[160] = jj_gen; + break label_108; + } + jj_consume_token(S); } - } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + ; + break; + default: + jj_la1[161] = jj_gen; + break label_107; + } + } + } catch (ParseException e) { + acceptMissingSemicolonBeforeRbrace(e); + } + } + + final public void includeDirectiveBlockContents() throws ParseException { + jj_consume_token(LBRACE); + label_109: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[162] = jj_gen; + break label_109; + } + jj_consume_token(S); + } + label_110: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case TO: + case FROM: + case DEBUG_SYM: + case WARN_SYM: + case IDENT: + case PERCENTAGE: + case HASH: + ; + break; + default: + jj_la1[163] = jj_gen; + break label_110; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case DEBUG_SYM: + case WARN_SYM: + case IDENT: + case HASH: + styleRuleOrDeclarationOrNestedProperties(); + break; + case TO: + case FROM: + case PERCENTAGE: + keyframeSelector(); + break; + default: + jj_la1[164] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + jj_consume_token(RBRACE); + label_111: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[165] = jj_gen; + break label_111; + } + jj_consume_token(S); + } + } + + final public String interpolation() throws ParseException { + Token n; + n = jj_consume_token(INTERPOLATION); + {if (true) return n.image;} + throw new Error("Missing return statement in function"); + } + + final public void listModifyDirective() throws ParseException { + String list = null; + String remove = null; + String separator = null; + String variable = null; + Token n = null; + Token type = null; + //refactor, remove those 3 LOOKAHEAD(5). + n = jj_consume_token(VARIABLE); + variable = n.image; + label_112: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[166] = jj_gen; + break label_112; + } + jj_consume_token(S); + } + jj_consume_token(COLON); + label_113: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[167] = jj_gen; + break label_113; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case APPEND: + type = jj_consume_token(APPEND); + break; + case REMOVE: + type = jj_consume_token(REMOVE); + break; + case CONTAINS: + type = jj_consume_token(CONTAINS); + break; + default: + jj_la1[168] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + label_114: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[169] = jj_gen; + break label_114; + } + jj_consume_token(S); + } + list = listModifyDirectiveArgs(0); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case RPARAN: + jj_consume_token(RPARAN); + break; + default: + jj_la1[170] = jj_gen; + ; + } + jj_consume_token(COMMA); + label_115: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[171] = jj_gen; + break label_115; + } + jj_consume_token(S); + } + remove = listModifyDirectiveArgs(1); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + label_116: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[172] = jj_gen; + break label_116; + } + jj_consume_token(S); + } + n = jj_consume_token(IDENT); + separator = n.image; + label_117: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[173] = jj_gen; + break label_117; + } + jj_consume_token(S); + } + break; + default: + jj_la1[174] = jj_gen; + ; + } + jj_consume_token(RPARAN); + switch (type.kind) { + case APPEND: + documentHandler.appendDirective(variable,list,remove,separator); + break; + case REMOVE: + documentHandler.removeDirective(variable,list,remove,separator); + break; + case CONTAINS: + if(variable == null){ + variable = "$var_"+UUID.randomUUID(); + } + documentHandler.containsDirective(variable,list,remove,separator); + break; + default: + break; + } + label_118: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[175] = jj_gen; + break label_118; + } + jj_consume_token(S); + } + jj_consume_token(SEMICOLON); + label_119: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[176] = jj_gen; + break label_119; + } + jj_consume_token(S); + } + } - /** - * @exception ParseException - * exception during the parse - */ - final public void appendDirective() throws ParseException { +/** + * @exception ParseException exception during the parse + */ + final public void appendDirective() throws ParseException { String list = null; String remove = null; String separator = null; String variable = null; Token n = null; - n = jj_consume_token(VARIABLE); - variable = n.image; - label_120: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[175] = jj_gen; - break label_120; - } - jj_consume_token(S); - } - jj_consume_token(COLON); - label_121: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[176] = jj_gen; - break label_121; - } - jj_consume_token(S); - } - jj_consume_token(APPEND); - label_122: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[177] = jj_gen; - break label_122; - } - jj_consume_token(S); - } - list = listModifyDirectiveArgs(0); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case RPARAN: - jj_consume_token(RPARAN); - break; + n = jj_consume_token(VARIABLE); + variable = n.image; + label_120: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[177] = jj_gen; + break label_120; + } + jj_consume_token(S); + } + jj_consume_token(COLON); + label_121: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[178] = jj_gen; + break label_121; + } + jj_consume_token(S); + } + jj_consume_token(APPEND); + label_122: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[179] = jj_gen; + break label_122; + } + jj_consume_token(S); + } + list = listModifyDirectiveArgs(0); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case RPARAN: + jj_consume_token(RPARAN); + break; + default: + jj_la1[180] = jj_gen; + ; + } + jj_consume_token(COMMA); + label_123: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[181] = jj_gen; + break label_123; + } + jj_consume_token(S); + } + remove = listModifyDirectiveArgs(1); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + label_124: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[178] = jj_gen; - ; - } - jj_consume_token(COMMA); - label_123: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[179] = jj_gen; - break label_123; - } - jj_consume_token(S); - } - remove = listModifyDirectiveArgs(1); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - jj_consume_token(COMMA); - label_124: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[180] = jj_gen; - break label_124; - } - jj_consume_token(S); - } - n = jj_consume_token(IDENT); - separator = n.image; - label_125: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[181] = jj_gen; - break label_125; - } - jj_consume_token(S); - } - break; + jj_la1[182] = jj_gen; + break label_124; + } + jj_consume_token(S); + } + n = jj_consume_token(IDENT); + separator = n.image; + label_125: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[182] = jj_gen; - ; + jj_la1[183] = jj_gen; + break label_125; } - jj_consume_token(RPARAN); - documentHandler.appendDirective(variable, list, remove, separator); + jj_consume_token(S); + } + break; + default: + jj_la1[184] = jj_gen; + ; } + jj_consume_token(RPARAN); + documentHandler.appendDirective(variable,list,remove,separator); + } - /** - * @exception ParseException - * exception during the parse - */ - final public void removeDirective() throws ParseException { - String list = null; - String remove = null; - String separator = null; - String variable = null; - Token n = null; - n = jj_consume_token(VARIABLE); - variable = n.image; - label_126: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[183] = jj_gen; - break label_126; - } - jj_consume_token(S); - } - jj_consume_token(COLON); - label_127: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[184] = jj_gen; - break label_127; - } - jj_consume_token(S); - } - jj_consume_token(REMOVE); - label_128: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[185] = jj_gen; - break label_128; - } - jj_consume_token(S); - } - list = listModifyDirectiveArgs(0); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case RPARAN: - jj_consume_token(RPARAN); - break; +/** + * @exception ParseException exception during the parse + */ + final public void removeDirective() throws ParseException { + String list = null; + String remove = null; + String separator = null; + String variable = null; + Token n = null; + n = jj_consume_token(VARIABLE); + variable = n.image; + label_126: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[185] = jj_gen; + break label_126; + } + jj_consume_token(S); + } + jj_consume_token(COLON); + label_127: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[186] = jj_gen; + break label_127; + } + jj_consume_token(S); + } + jj_consume_token(REMOVE); + label_128: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[187] = jj_gen; + break label_128; + } + jj_consume_token(S); + } + list = listModifyDirectiveArgs(0); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case RPARAN: + jj_consume_token(RPARAN); + break; + default: + jj_la1[188] = jj_gen; + ; + } + jj_consume_token(COMMA); + label_129: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[189] = jj_gen; + break label_129; + } + jj_consume_token(S); + } + remove = listModifyDirectiveArgs(1); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + label_130: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[186] = jj_gen; - ; - } - jj_consume_token(COMMA); - label_129: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[187] = jj_gen; - break label_129; - } - jj_consume_token(S); - } - remove = listModifyDirectiveArgs(1); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - jj_consume_token(COMMA); - label_130: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[188] = jj_gen; - break label_130; - } - jj_consume_token(S); - } - n = jj_consume_token(IDENT); - separator = n.image; - label_131: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[189] = jj_gen; - break label_131; - } - jj_consume_token(S); - } - break; + jj_la1[190] = jj_gen; + break label_130; + } + jj_consume_token(S); + } + n = jj_consume_token(IDENT); + separator = n.image; + label_131: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[190] = jj_gen; - ; + jj_la1[191] = jj_gen; + break label_131; } - jj_consume_token(RPARAN); - documentHandler.removeDirective(variable, list, remove, separator); + jj_consume_token(S); + } + break; + default: + jj_la1[192] = jj_gen; + ; } + jj_consume_token(RPARAN); + documentHandler.removeDirective(variable,list,remove,separator); + } - /** - * @exception ParseException - * exception during the parse - */ - final public String containsDirective() throws ParseException { +/** + * @exception ParseException exception during the parse + */ + final public String containsDirective() throws ParseException { String list = null; String remove = null; String separator = null; String variable = null; Token n = null; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case VARIABLE: - n = jj_consume_token(VARIABLE); - variable = n.image; - label_132: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[191] = jj_gen; - break label_132; - } - jj_consume_token(S); - } - jj_consume_token(COLON); - label_133: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[192] = jj_gen; - break label_133; - } - jj_consume_token(S); - } - break; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case VARIABLE: + n = jj_consume_token(VARIABLE); + variable = n.image; + label_132: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[193] = jj_gen; - ; - } - jj_consume_token(CONTAINS); - label_134: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[194] = jj_gen; - break label_134; - } - jj_consume_token(S); - } - list = listModifyDirectiveArgs(0); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case RPARAN: - jj_consume_token(RPARAN); - break; + jj_la1[193] = jj_gen; + break label_132; + } + jj_consume_token(S); + } + jj_consume_token(COLON); + label_133: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[195] = jj_gen; - ; - } - jj_consume_token(COMMA); - label_135: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[196] = jj_gen; - break label_135; - } - jj_consume_token(S); - } - remove = listModifyDirectiveArgs(1); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - jj_consume_token(COMMA); - label_136: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[197] = jj_gen; - break label_136; - } - jj_consume_token(S); - } - n = jj_consume_token(IDENT); - separator = n.image; - label_137: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[198] = jj_gen; - break label_137; - } - jj_consume_token(S); - } - break; + jj_la1[194] = jj_gen; + break label_133; + } + jj_consume_token(S); + } + break; + default: + jj_la1[195] = jj_gen; + ; + } + jj_consume_token(CONTAINS); + label_134: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[196] = jj_gen; + break label_134; + } + jj_consume_token(S); + } + list = listModifyDirectiveArgs(0); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case RPARAN: + jj_consume_token(RPARAN); + break; + default: + jj_la1[197] = jj_gen; + ; + } + jj_consume_token(COMMA); + label_135: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[198] = jj_gen; + break label_135; + } + jj_consume_token(S); + } + remove = listModifyDirectiveArgs(1); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + label_136: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[199] = jj_gen; - ; - } - jj_consume_token(RPARAN); - /* - * if it is not in the form like - * "$contains : contains($items, .v-button);"for example in @if, like - * "@if (contains(a b c, b))", then create a tempvariable for contains(a - * b c, b); - */ - if (variable == null) { - variable = "$var_" + UUID.randomUUID(); - } - documentHandler.containsDirective(variable, list, remove, separator); - { - if (true) { - return variable; - } - } - throw new Error("Missing return statement in function"); - } - - String listModifyDirectiveArgs(int nest) throws ParseException { + jj_la1[199] = jj_gen; + break label_136; + } + jj_consume_token(S); + } + n = jj_consume_token(IDENT); + separator = n.image; + label_137: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[200] = jj_gen; + break label_137; + } + jj_consume_token(S); + } + break; + default: + jj_la1[201] = jj_gen; + ; + } + jj_consume_token(RPARAN); + /* + *if it is not in the form like "$contains : contains($items, .v-button);" + *for example in @if, like "@if (contains(a b c, b))", then create a temp + *variable for contains(a b c, b); + */ + if(variable == null){ + variable = "$var_"+UUID.randomUUID(); + } + documentHandler.containsDirective(variable,list,remove,separator); + {if (true) return variable;} + throw new Error("Missing return statement in function"); + } + + String listModifyDirectiveArgs(int nest) throws ParseException { String list = ""; int nesting = nest; Token t = null; - while (true) { - t = getToken(1); - String s = t.image; - if (t.kind == VARIABLE || t.kind == IDENT) { - list += s; - } else if (s.toLowerCase().equals("auto") - || s.toLowerCase().equals("space") - || s.toLowerCase().equals("comma")) { - int i = 2; - Token temp = getToken(i); - boolean isLast = true; - while (temp.kind != SEMICOLON) { - if (temp.kind != RPARAN || temp.kind != S) { - isLast = false; - } - i++; - temp = getToken(i); - } + while(true) + { + t = getToken(1); + String s = t.image; + if(t.kind == VARIABLE||t.kind == IDENT) + { + list += s; + }else if(s.toLowerCase().equals("auto")||s.toLowerCase().equals("space")||s.toLowerCase().equals("comma")) + { + int i = 2; + Token temp = getToken(i); + boolean isLast = true; + while(temp.kind != SEMICOLON) + { + if(temp.kind != RPARAN || temp.kind != S) + { + isLast = false; + } + i++; + temp = getToken(i); + } - if (isLast) { - return list; - } - } else if (t.kind == STRING) { - list += s.substring(1, s.length()).substring(0, s.length() - 2); - - } else if (t.kind == LPARAN) { - nesting++; - if (nesting > nest + 1) { - throw new CSSParseException( - "Only one ( ) pair per parameter allowed", - getLocator()); - } - } else if (t.kind == RPARAN) { - nesting--; - if (nesting == 0) { - return list; - } - } else if (t.kind == COMMA) { - if (nesting == nest) { - return list; - } else { - list += ","; + if(isLast) + { + return list; + } } + else if(t.kind == STRING) + { + list += s.substring(1,s.length()).substring(0,s.length()-2); - } else if (t.kind == S) { - list += " "; - } else if (t.kind == LBRACE) { - throw new CSSParseException("Invalid token,'{' found", - getLocator()); - } + }else if(t.kind == LPARAN) + { + nesting++; + if(nesting > nest+1) + { + throw new CSSParseException("Only one ( ) pair per parameter allowed", getLocator()); + } + }else if(t.kind == RPARAN) + { + nesting--; + if(nesting == 0) + { + return list; + } + } else if(t.kind == COMMA) + { + if(nesting == nest) + { + return list; + }else + { + list += ","; + } - getNextToken(); - } - } + }else if(t.kind == S) + { + list += " "; + } else if(t.kind == LBRACE) + { + throw new CSSParseException("Invalid token,'{' found", getLocator()); + } - final public Node returnDirective() throws ParseException { - String raw; - raw = skipStatement(); - { - if (true) { - return null; - } + getNextToken(); } - throw new Error("Missing return statement in function"); - } - - final public void debuggingDirective() throws ParseException { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case DEBUG_SYM: - debugDirective(); - break; - case WARN_SYM: - warnDirective(); - break; + } + + final public Node returnDirective() throws ParseException { + String raw; + raw = skipStatement(); + {if (true) return null;} + throw new Error("Missing return statement in function"); + } + + final public void debuggingDirective() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DEBUG_SYM: + debugDirective(); + break; + case WARN_SYM: + warnDirective(); + break; + default: + jj_la1[202] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + + final public void debugDirective() throws ParseException { + jj_consume_token(DEBUG_SYM); + String content = skipStatementUntil(new int[] {SEMICOLON,RBRACE,EOF}); + // TODO should evaluate the content expression, call documentHandler.debugDirective() etc. + Logger.getLogger(Parser.class.getName()).log(Level.INFO, content); + try { + jj_consume_token(SEMICOLON); + label_138: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[200] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - - final public void debugDirective() throws ParseException { - jj_consume_token(DEBUG_SYM); - String content = skipStatementUntilSemiColon(); - // TODO should evaluate the content expression, call - // documentHandler.debugDirective() etc. - System.out.println(content); - label_138: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[201] = jj_gen; - break label_138; - } - jj_consume_token(S); - } - } - - final public void warnDirective() throws ParseException { - jj_consume_token(WARN_SYM); - String content = skipStatementUntilSemiColon(); - // TODO should evaluate the content expression, call - // documentHandler.warnDirective() etc. - System.err.println(content); - label_139: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[202] = jj_gen; - break label_139; - } - jj_consume_token(S); - } - } - - final public Node forDirective() throws ParseException { - String var; - String from; - String to; - boolean exclusive; - String body; - Token tok; - var = variableName(); - int[] toThrough = { TO, THROUGH }; + jj_la1[203] = jj_gen; + break label_138; + } + jj_consume_token(S); + } + } catch (ParseException e) { + acceptMissingSemicolonBeforeRbrace(e); + } + } + + final public void warnDirective() throws ParseException { + jj_consume_token(WARN_SYM); + String content = skipStatementUntil(new int[] {SEMICOLON,RBRACE,EOF}); + // TODO should evaluate the content expression, call documentHandler.warnDirective() etc. + Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, content); + try { + jj_consume_token(SEMICOLON); + label_139: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[204] = jj_gen; + break label_139; + } + jj_consume_token(S); + } + } catch (ParseException e) { + acceptMissingSemicolonBeforeRbrace(e); + } + } + + final public Node forDirective() throws ParseException { + String var; + String from; + String to; + boolean exclusive; + String body; + Token tok; + var = variableName(); + int[] toThrough = {TO, THROUGH}; from = skipStatementUntil(toThrough); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case TO: - tok = jj_consume_token(TO); - exclusive = true; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case TO: + tok = jj_consume_token(TO); + exclusive = true; + break; + case THROUGH: + tok = jj_consume_token(THROUGH); + exclusive = false; + break; + default: + jj_la1[205] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + to = skipStatementUntilLeftBrace(); + label_140: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[206] = jj_gen; + break label_140; + } + jj_consume_token(S); + } + body = skipStatement(); + {if (true) return documentHandler.forDirective(var, from, to, exclusive, body);} + throw new Error("Missing return statement in function"); + } + + final public Node whileDirective() throws ParseException { + String condition; + String body; + condition = skipStatementUntilLeftBrace(); + body = skipStatement(); + {if (true) return documentHandler.whileDirective(condition, body);} + throw new Error("Missing return statement in function"); + } + + final public void extendDirective() throws ParseException { + ArrayList<String> list; + jj_consume_token(EXTEND_SYM); + label_141: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[207] = jj_gen; + break label_141; + } + jj_consume_token(S); + } + list = selectorList(); + documentHandler.extendDirective(list); + try { + label_142: + while (true) { + jj_consume_token(SEMICOLON); + label_143: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; break; - case THROUGH: - tok = jj_consume_token(THROUGH); - exclusive = false; + default: + jj_la1[208] = jj_gen; + break label_143; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + ; + break; + default: + jj_la1[209] = jj_gen; + break label_142; + } + } + } catch (ParseException e) { + acceptMissingSemicolonBeforeRbrace(e); + } + } + + final public void contentDirective() throws ParseException { + jj_consume_token(CONTENT_SYM); + label_144: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[210] = jj_gen; + break label_144; + } + jj_consume_token(S); + } + try { + label_145: + while (true) { + jj_consume_token(SEMICOLON); + label_146: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; break; + default: + jj_la1[211] = jj_gen; + break label_146; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + ; + break; default: - jj_la1[203] = jj_gen; + jj_la1[212] = jj_gen; + break label_145; + } + } + } catch (ParseException e) { + acceptMissingSemicolonBeforeRbrace(e); + } + documentHandler.contentDirective(); + } + + Node importDirective() throws ParseException { + return null; + } + + Node charsetDirective() throws ParseException { + return null; + } + + Node mozDocumentDirective() throws ParseException { + return null; + } + + Node supportsDirective() throws ParseException { + return null; + } + + final public void nestedProperties() throws ParseException { + String name; +LexicalUnit exp; + name = property(); + jj_consume_token(COLON); + label_147: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[213] = jj_gen; + break label_147; + } + jj_consume_token(S); + } + jj_consume_token(LBRACE); + label_148: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[214] = jj_gen; + break label_148; + } + jj_consume_token(S); + } + documentHandler.startNestedProperties(name); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + declaration(); + break; + default: + jj_la1[215] = jj_gen; + ; + } + label_149: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + ; + break; + default: + jj_la1[216] = jj_gen; + break label_149; + } + jj_consume_token(SEMICOLON); + label_150: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[217] = jj_gen; + break label_150; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + declaration(); + break; + default: + jj_la1[218] = jj_gen; + ; + } + } + jj_consume_token(RBRACE); + documentHandler.endNestedProperties(name); + label_151: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[219] = jj_gen; + break label_151; + } + jj_consume_token(S); + } + } + +/** + * @exception ParseException exception during the parse + */ + final public void styleRuleOrDeclarationOrNestedProperties() throws ParseException { + try { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DEBUG_SYM: + case WARN_SYM: + debuggingDirective(); + break; + default: + jj_la1[220] = jj_gen; + if (jj_2_6(2147483647)) { + styleRule(); + } else if (jj_2_7(3)) { + declarationOrNestedProperties(); + } else { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case IDENT: + case HASH: + styleRule(); + break; + default: + jj_la1[221] = jj_gen; jj_consume_token(-1); throw new ParseException(); - } - to = skipStatementUntilLeftBrace(); - label_140: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[204] = jj_gen; - break label_140; - } - jj_consume_token(S); - } - body = skipStatement(); - { - if (true) { - return documentHandler.forDirective(var, from, to, exclusive, - body); - } - } - throw new Error("Missing return statement in function"); - } - - final public Node whileDirective() throws ParseException { - String condition; - String body; - condition = skipStatementUntilLeftBrace(); - body = skipStatement(); - { - if (true) { - return documentHandler.whileDirective(condition, body); - } - } - throw new Error("Missing return statement in function"); - } - - final public void extendDirective() throws ParseException { - ArrayList<String> list; - jj_consume_token(EXTEND_SYM); - label_141: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[205] = jj_gen; - break label_141; - } - jj_consume_token(S); - } - list = selectorList(); - label_142: while (true) { - jj_consume_token(SEMICOLON); - label_143: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[206] = jj_gen; - break label_143; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - ; - break; - default: - jj_la1[207] = jj_gen; - break label_142; - } - } - documentHandler.extendDirective(list); - } - - final public void contentDirective() throws ParseException { - jj_consume_token(CONTENT_SYM); - label_144: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[208] = jj_gen; - break label_144; - } - jj_consume_token(S); - } - label_145: while (true) { - jj_consume_token(SEMICOLON); - label_146: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[209] = jj_gen; - break label_146; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - ; - break; - default: - jj_la1[210] = jj_gen; - break label_145; - } - } - documentHandler.contentDirective(); - } - - Node importDirective() throws ParseException { - return null; - } - - Node charsetDirective() throws ParseException { - return null; - } - - Node mozDocumentDirective() throws ParseException { - return null; - } - - Node supportsDirective() throws ParseException { - return null; + } + } + } + } catch (JumpException e) { + skipAfterExpression(); + // reportWarningSkipText(getLocator(), skipAfterExpression()); + + } catch (ParseException e) { + if (errorHandler != null) { + if (e.currentToken != null) { + LocatorImpl li = new LocatorImpl(this, + e.currentToken.next.beginLine, + e.currentToken.next.beginColumn-1); + reportError(li, e); + } else { + reportError(getLocator(), e); + } + skipAfterExpression(); + /* + LocatorImpl loc = (LocatorImpl) getLocator(); + loc.column--; + reportWarningSkipText(loc, skipAfterExpression()); + */ + } else { + skipAfterExpression(); + } } + } - final public void nestedProperties() throws ParseException { - String name; - LexicalUnit exp; - name = property(); - jj_consume_token(COLON); - label_147: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[211] = jj_gen; - break label_147; - } - jj_consume_token(S); - } +/** + * @exception ParseException exception during the parse + */ + final public void declarationOrNestedProperties() throws ParseException { + boolean important = false; + String name; + LexicalUnitImpl exp; + Token save; + String comment = null; + try { + name = property(); + save = token; + jj_consume_token(COLON); + label_152: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[222] = jj_gen; + break label_152; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case MINUS: + case DOT: + case TO: + case THROUGH: + case FROM: + case STRING: + case IDENT: + case NUMBER: + case URL: + case VARIABLE: + case PERCENTAGE: + case PT: + case MM: + case CM: + case PC: + case IN: + case PX: + case EMS: + case LEM: + case REM: + case EXS: + case DEG: + case RAD: + case GRAD: + case MS: + case SECOND: + case HZ: + case KHZ: + case DIMEN: + case HASH: + case UNICODERANGE: + case FUNCTION: + exp = expr(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IMPORTANT_SYM: + important = prio(); + break; + default: + jj_la1[223] = jj_gen; + ; + } + Token next = getToken(1); + if(next.kind == SEMICOLON || next.kind == RBRACE){ + while(next.kind == SEMICOLON){ + skipStatement(); + next = getToken(1); + } + //only add special token kept for sprites '/**' + if(token.specialToken!=null && token.specialToken!=null && token.specialToken.image.startsWith("/**")){ + documentHandler.property(name, exp, important, token.specialToken.image); + }else{ + documentHandler.property(name, exp, important, null); + } + } + break; + case LBRACE: jj_consume_token(LBRACE); - label_148: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[212] = jj_gen; - break label_148; - } - jj_consume_token(S); - } - documentHandler.startNestedProperties(name); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + label_153: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[224] = jj_gen; + break label_153; + } + jj_consume_token(S); + } + documentHandler.startNestedProperties(name); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case INTERPOLATION: case IDENT: - declaration(); - break; + declaration(); + break; default: - jj_la1[213] = jj_gen; - ; - } - label_149: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - ; - break; - default: - jj_la1[214] = jj_gen; - break label_149; - } - jj_consume_token(SEMICOLON); - label_150: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[215] = jj_gen; - break label_150; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - declaration(); - break; - default: - jj_la1[216] = jj_gen; - ; - } - } - jj_consume_token(RBRACE); - documentHandler.endNestedProperties(name); - label_151: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[217] = jj_gen; - break label_151; - } - jj_consume_token(S); - } - } - - /** - * @exception ParseException - * exception during the parse - */ - final public void styleRuleOrDeclarationOrNestedProperties() - throws ParseException { - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case DEBUG_SYM: - case WARN_SYM: - debuggingDirective(); - break; - default: - jj_la1[218] = jj_gen; - if (jj_2_6(2147483647)) { - styleRule(); - } else if (jj_2_7(3)) { - declarationOrNestedProperties(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case IDENT: - case HASH: - styleRule(); - break; - default: - jj_la1[219] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - } - } catch (JumpException e) { - skipAfterExpression(); - // reportWarningSkipText(getLocator(), skipAfterExpression()); - - } catch (ParseException e) { - if (errorHandler != null) { - if (e.currentToken != null) { - LocatorImpl li = new LocatorImpl(this, - e.currentToken.next.beginLine, - e.currentToken.next.beginColumn - 1); - reportError(li, e); - } else { - reportError(getLocator(), e); - } - skipAfterExpression(); - /* - * LocatorImpl loc = (LocatorImpl) getLocator(); loc.column--; - * reportWarningSkipText(loc, skipAfterExpression()); - */ - } else { - skipAfterExpression(); - } - } - } - - /** - * @exception ParseException - * exception during the parse - */ - final public void declarationOrNestedProperties() throws ParseException { - boolean important = false; - String name; - LexicalUnitImpl exp; - Token save; - String comment = null; - try { - name = property(); - save = token; - jj_consume_token(COLON); - label_152: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[220] = jj_gen; - break label_152; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case MINUS: - case DOT: - case TO: - case THROUGH: - case FROM: - case STRING: - case IDENT: - case NUMBER: - case URL: - case VARIABLE: - case PERCENTAGE: - case PT: - case MM: - case CM: - case PC: - case IN: - case PX: - case EMS: - case LEM: - case REM: - case EXS: - case DEG: - case RAD: - case GRAD: - case MS: - case SECOND: - case HZ: - case KHZ: - case DIMEN: - case HASH: - case UNICODERANGE: - case FUNCTION: - exp = expr(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IMPORTANT_SYM: - important = prio(); - break; - default: - jj_la1[221] = jj_gen; - ; - } - Token next = getToken(1); - if (next.kind == SEMICOLON || next.kind == RBRACE) { - while (next.kind == SEMICOLON) { - skipStatement(); - next = getToken(1); - } - // only add special token kept for sprites '/**' - if (token.specialToken != null - && token.specialToken != null - && token.specialToken.image.startsWith("/**")) { - documentHandler.property(name, exp, important, - token.specialToken.image); - } else { - documentHandler.property(name, exp, important, null); - } - } - break; - case LBRACE: - jj_consume_token(LBRACE); - label_153: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[222] = jj_gen; - break label_153; - } - jj_consume_token(S); - } - documentHandler.startNestedProperties(name); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - declaration(); - break; - default: - jj_la1[223] = jj_gen; - ; - } - label_154: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - ; - break; - default: - jj_la1[224] = jj_gen; - break label_154; - } - jj_consume_token(SEMICOLON); - label_155: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[225] = jj_gen; - break label_155; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - declaration(); - break; - default: - jj_la1[226] = jj_gen; - ; - } - } - jj_consume_token(RBRACE); - label_156: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[227] = jj_gen; - break label_156; - } - jj_consume_token(S); - } - documentHandler.endNestedProperties(name); - break; - default: - jj_la1[228] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } catch (JumpException e) { - skipAfterExpression(); - // reportWarningSkipText(getLocator(), skipAfterExpression()); - - } catch (NumberFormatException e) { - if (errorHandler != null) { - errorHandler.error(new CSSParseException("Invalid number " - + e.getMessage(), getLocator(), e)); - } - reportWarningSkipText(getLocator(), skipAfterExpression()); - } catch (ParseException e) { - if (errorHandler != null) { - if (e.currentToken != null) { - LocatorImpl li = new LocatorImpl(this, - e.currentToken.next.beginLine, - e.currentToken.next.beginColumn - 1); - reportError(li, e); - } else { - reportError(getLocator(), e); - } - skipAfterExpression(); - /* - * LocatorImpl loc = (LocatorImpl) getLocator(); loc.column--; - * reportWarningSkipText(loc, skipAfterExpression()); - */ - } else { - skipAfterExpression(); - } + jj_la1[225] = jj_gen; + ; } - } - - /** - * @exception ParseException - * exception during the parse - */ - final public void declaration() throws ParseException { - boolean important = false; - String name; - LexicalUnit exp; - Token save; - try { - name = property(); - save = token; - jj_consume_token(COLON); - label_157: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[229] = jj_gen; - break label_157; - } - jj_consume_token(S); - } - exp = expr(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IMPORTANT_SYM: - important = prio(); - break; - default: - jj_la1[230] = jj_gen; - ; - } - documentHandler.property(name, exp, important); - } catch (JumpException e) { - skipAfterExpression(); - // reportWarningSkipText(getLocator(), skipAfterExpression()); - - } catch (NumberFormatException e) { - if (errorHandler != null) { - errorHandler.error(new CSSParseException("Invalid number " - + e.getMessage(), getLocator(), e)); - } - reportWarningSkipText(getLocator(), skipAfterExpression()); - } catch (ParseException e) { - if (errorHandler != null) { - if (e.currentToken != null) { - LocatorImpl li = new LocatorImpl(this, - e.currentToken.next.beginLine, - e.currentToken.next.beginColumn - 1); - reportError(li, e); - } else { - reportError(getLocator(), e); - } - skipAfterExpression(); - /* - * LocatorImpl loc = (LocatorImpl) getLocator(); loc.column--; - * reportWarningSkipText(loc, skipAfterExpression()); - */ - } else { - skipAfterExpression(); - } - } - } - - /** - * @exception ParseException - * exception during the parse - */ - final public boolean prio() throws ParseException { - jj_consume_token(IMPORTANT_SYM); - label_158: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[231] = jj_gen; - break label_158; - } - jj_consume_token(S); - } - { - if (true) { - return true; - } - } - throw new Error("Missing return statement in function"); - } - - final public boolean guarded() throws ParseException { - jj_consume_token(GUARDED_SYM); - label_159: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + label_154: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + ; + break; + default: + jj_la1[226] = jj_gen; + break label_154; + } + jj_consume_token(SEMICOLON); + label_155: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case S: - ; - break; + ; + break; default: - jj_la1[232] = jj_gen; - break label_159; + jj_la1[227] = jj_gen; + break label_155; } jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + declaration(); + break; + default: + jj_la1[228] = jj_gen; + ; + } } - { - if (true) { - return true; - } - } - throw new Error("Missing return statement in function"); + jj_consume_token(RBRACE); + label_156: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[229] = jj_gen; + break label_156; + } + jj_consume_token(S); + } + documentHandler.endNestedProperties(name); + break; + default: + jj_la1[230] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } catch (JumpException e) { + skipAfterExpression(); + // reportWarningSkipText(getLocator(), skipAfterExpression()); + + } catch (NumberFormatException e) { + if (errorHandler != null) { + errorHandler.error(new CSSParseException("Invalid number " + + e.getMessage(), + getLocator(), + e)); + } + reportWarningSkipText(getLocator(), skipAfterExpression()); + } catch (ParseException e) { + if (errorHandler != null) { + if (e.currentToken != null) { + LocatorImpl li = new LocatorImpl(this, + e.currentToken.next.beginLine, + e.currentToken.next.beginColumn-1); + reportError(li, e); + } else { + reportError(getLocator(), e); + } + skipAfterExpression(); + /* + LocatorImpl loc = (LocatorImpl) getLocator(); + loc.column--; + reportWarningSkipText(loc, skipAfterExpression()); + */ + } else { + skipAfterExpression(); + } } + } - /** - * @exception ParseException - * exception during the parse - */ - final public LexicalUnitImpl operator(LexicalUnitImpl prev) - throws ParseException { - Token n; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - /* - * (comments copied from basic_arithmetics.scss)supports: 1. - * standard arithmetic operations (+, -, *, /, %) 2. / is treated as - * css operator, unless one of its operands is variable or there is - * another binary arithmetic operatorlimits: 1. cannot mix - * arithmetic and css operations, e.g. "margin: 1px + 3px 2px" will - * fail 2. space between add and minus operator and their following - * operand is mandatory. e.g. "1 + 2" is valid, "1+2" is not 3. - * parenthesis is not supported now. - */ - n = jj_consume_token(COMMA); - label_160: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[233] = jj_gen; - break label_160; - } - jj_consume_token(S); - } - { - if (true) { - return LexicalUnitImpl.createComma(n.beginLine, - n.beginColumn, prev); - } - } - break; - case DIV: - n = jj_consume_token(DIV); - label_161: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[234] = jj_gen; - break label_161; - } - jj_consume_token(S); - } - { - if (true) { - return LexicalUnitImpl.createSlash(n.beginLine, - n.beginColumn, prev); - } - } - break; - case ANY: - n = jj_consume_token(ANY); - label_162: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[235] = jj_gen; - break label_162; - } - jj_consume_token(S); - } - { - if (true) { - return LexicalUnitImpl.createMultiply(n.beginLine, - n.beginColumn, prev); - } - } - break; - case MOD: - n = jj_consume_token(MOD); - label_163: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[236] = jj_gen; - break label_163; - } - jj_consume_token(S); - } - { - if (true) { - return LexicalUnitImpl.createModulo(n.beginLine, - n.beginColumn, prev); - } - } - break; - case PLUS: - n = jj_consume_token(PLUS); - label_164: while (true) { - jj_consume_token(S); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[237] = jj_gen; - break label_164; - } - } - { - if (true) { - return LexicalUnitImpl.createAdd(n.beginLine, - n.beginColumn, prev); - } - } - break; - case MINUS: - n = jj_consume_token(MINUS); - label_165: while (true) { - jj_consume_token(S); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[238] = jj_gen; - break label_165; - } - } - { - if (true) { - return LexicalUnitImpl.createMinus(n.beginLine, - n.beginColumn, prev); - } - } - break; +/** + * @exception ParseException exception during the parse + */ + final public void declaration() throws ParseException { + boolean important = false; + String name; + LexicalUnit exp; + Token save; + try { + name = property(); + save = token; + jj_consume_token(COLON); + label_157: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[239] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - throw new Error("Missing return statement in function"); - } + jj_la1[231] = jj_gen; + break label_157; + } + jj_consume_token(S); + } + exp = expr(); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IMPORTANT_SYM: + important = prio(); + break; + default: + jj_la1[232] = jj_gen; + ; + } + documentHandler.property(name, exp, important); + } catch (JumpException e) { + skipAfterExpression(); + // reportWarningSkipText(getLocator(), skipAfterExpression()); + + } catch (NumberFormatException e) { + if (errorHandler != null) { + errorHandler.error(new CSSParseException("Invalid number " + + e.getMessage(), + getLocator(), + e)); + } + reportWarningSkipText(getLocator(), skipAfterExpression()); + } catch (ParseException e) { + if (errorHandler != null) { + if (e.currentToken != null) { + LocatorImpl li = new LocatorImpl(this, + e.currentToken.next.beginLine, + e.currentToken.next.beginColumn-1); + reportError(li, e); + } else { + reportError(getLocator(), e); + } + skipAfterExpression(); + /* + LocatorImpl loc = (LocatorImpl) getLocator(); + loc.column--; + reportWarningSkipText(loc, skipAfterExpression()); + */ + } else { + skipAfterExpression(); + } + } + } - /** - * @exception ParseException - * exception during the parse - */ - final public LexicalUnitImpl expr() throws ParseException { - LexicalUnitImpl first, res; - char op; - first = term(null); - res = first; - label_166: while (true) { - if (jj_2_8(2)) { - ; - } else { - break label_166; - } - if (jj_2_9(2)) { - res = operator(res); - } else { - ; - } - res = term(res); - } - { - if (true) { - return first; - } - } - throw new Error("Missing return statement in function"); - } +/** + * @exception ParseException exception during the parse + */ + final public boolean prio() throws ParseException { + jj_consume_token(IMPORTANT_SYM); + label_158: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[233] = jj_gen; + break label_158; + } + jj_consume_token(S); + } + {if (true) return true;} + throw new Error("Missing return statement in function"); + } + + final public boolean guarded() throws ParseException { + jj_consume_token(GUARDED_SYM); + label_159: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[234] = jj_gen; + break label_159; + } + jj_consume_token(S); + } + {if (true) return true;} + throw new Error("Missing return statement in function"); + } - /** - * @exception ParseException - * exception during the parse - */ - final public char unaryOperator() throws ParseException { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case MINUS: - jj_consume_token(MINUS); - { - if (true) { - return '-'; - } - } - break; - case PLUS: - jj_consume_token(PLUS); - { - if (true) { - return '+'; - } - } - break; +/** + * @exception ParseException exception during the parse + */ + final public LexicalUnitImpl operator(LexicalUnitImpl prev) throws ParseException { + Token n; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + /* (comments copied from basic_arithmetics.scss) + *supports: + * 1. standard arithmetic operations (+, -, *, /, %) + * 2. / is treated as css operator, unless one of its operands is variable or there is another binary arithmetic operator + *limits: + * 1. cannot mix arithmetic and css operations, e.g. "margin: 1px + 3px 2px" will fail + * 2. space between add and minus operator and their following operand is mandatory. e.g. "1 + 2" is valid, "1+2" is not + * 3. parenthesis is not supported now. + */ + n = jj_consume_token(COMMA); + label_160: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[240] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - throw new Error("Missing return statement in function"); - } - - /** - * @exception ParseException - * exception during the parse - */ - final public LexicalUnitImpl term(LexicalUnitImpl prev) - throws ParseException { - LexicalUnitImpl result = null; - Token n = null; - char op = ' '; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case MINUS: - case DOT: - case TO: - case THROUGH: - case FROM: - case STRING: - case IDENT: - case NUMBER: - case URL: - case PERCENTAGE: - case PT: - case MM: - case CM: - case PC: - case IN: - case PX: - case EMS: - case LEM: - case REM: - case EXS: - case DEG: - case RAD: - case GRAD: - case MS: - case SECOND: - case HZ: - case KHZ: - case DIMEN: - case HASH: - case UNICODERANGE: - case FUNCTION: - result = nonVariableTerm(prev); - break; - case VARIABLE: - result = variableTerm(prev); - break; + jj_la1[235] = jj_gen; + break label_160; + } + jj_consume_token(S); + } + {if (true) return LexicalUnitImpl.createComma(n.beginLine, + n.beginColumn, + prev);} + break; + case DIV: + n = jj_consume_token(DIV); + label_161: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; default: - jj_la1[241] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - { - if (true) { - return result; - } - } - throw new Error("Missing return statement in function"); - } + jj_la1[236] = jj_gen; + break label_161; + } + jj_consume_token(S); + } + {if (true) return LexicalUnitImpl.createSlash(n.beginLine, + n.beginColumn, + prev);} + break; + case ANY: + n = jj_consume_token(ANY); + label_162: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[237] = jj_gen; + break label_162; + } + jj_consume_token(S); + } + {if (true) return LexicalUnitImpl.createMultiply(n.beginLine, + n.beginColumn, + prev);} + break; + case MOD: + n = jj_consume_token(MOD); + label_163: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[238] = jj_gen; + break label_163; + } + jj_consume_token(S); + } + {if (true) return LexicalUnitImpl.createModulo(n.beginLine, + n.beginColumn, + prev);} + break; + case PLUS: + n = jj_consume_token(PLUS); + label_164: + while (true) { + jj_consume_token(S); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[239] = jj_gen; + break label_164; + } + } + {if (true) return LexicalUnitImpl.createAdd(n.beginLine, + n.beginColumn, + prev);} + break; + case MINUS: + n = jj_consume_token(MINUS); + label_165: + while (true) { + jj_consume_token(S); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[240] = jj_gen; + break label_165; + } + } + {if (true) return LexicalUnitImpl.createMinus(n.beginLine, + n.beginColumn, + prev);} + break; + default: + jj_la1[241] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } - final public LexicalUnitImpl variableTerm(LexicalUnitImpl prev) - throws ParseException { - LexicalUnitImpl result = null; - String varName = ""; - varName = variableName(); - result = LexicalUnitImpl.createVariable(token.beginLine, - token.beginColumn, prev, varName); - { - if (true) { - return result; - } - } - throw new Error("Missing return statement in function"); - } +/** + * @exception ParseException exception during the parse + */ + final public LexicalUnitImpl expr() throws ParseException { + LexicalUnitImpl first, res; + char op; + first = term(null); + res = first; + label_166: + while (true) { + if (jj_2_8(2)) { + ; + } else { + break label_166; + } + if (jj_2_9(2)) { + res = operator(res); + } else { + ; + } + res = term(res); + } + {if (true) return first;} + throw new Error("Missing return statement in function"); + } - final public LexicalUnitImpl nonVariableTerm(LexicalUnitImpl prev) - throws ParseException { - LexicalUnitImpl result = null; - Token n = null; - char op = ' '; - String varName; - String s = ""; - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case MINUS: - case NUMBER: - case PERCENTAGE: - case PT: - case MM: - case CM: - case PC: - case IN: - case PX: - case EMS: - case LEM: - case REM: - case EXS: - case DEG: - case RAD: - case GRAD: - case MS: - case SECOND: - case HZ: - case KHZ: - case DIMEN: - case FUNCTION: - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case MINUS: - op = unaryOperator(); - break; - default: - jj_la1[242] = jj_gen; - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case NUMBER: - n = jj_consume_token(NUMBER); - result = LexicalUnitImpl.createNumber(n.beginLine, - n.beginColumn, prev, number(op, n, 0)); - break; - case PERCENTAGE: - n = jj_consume_token(PERCENTAGE); - result = LexicalUnitImpl.createPercentage(n.beginLine, - n.beginColumn, prev, number(op, n, 1)); - break; - case PT: - n = jj_consume_token(PT); - result = LexicalUnitImpl.createPT(n.beginLine, n.beginColumn, - prev, number(op, n, 2)); - break; - case CM: - n = jj_consume_token(CM); - result = LexicalUnitImpl.createCM(n.beginLine, n.beginColumn, - prev, number(op, n, 2)); - break; - case MM: - n = jj_consume_token(MM); - result = LexicalUnitImpl.createMM(n.beginLine, n.beginColumn, - prev, number(op, n, 2)); - break; - case PC: - n = jj_consume_token(PC); - result = LexicalUnitImpl.createPC(n.beginLine, n.beginColumn, - prev, number(op, n, 2)); - break; - case IN: - n = jj_consume_token(IN); - result = LexicalUnitImpl.createIN(n.beginLine, n.beginColumn, - prev, number(op, n, 2)); - break; - case PX: - n = jj_consume_token(PX); - result = LexicalUnitImpl.createPX(n.beginLine, n.beginColumn, - prev, number(op, n, 2)); - break; - case EMS: - n = jj_consume_token(EMS); - result = LexicalUnitImpl.createEMS(n.beginLine, n.beginColumn, - prev, number(op, n, 2)); - break; - case LEM: - n = jj_consume_token(LEM); - result = LexicalUnitImpl.createLEM(n.beginLine, n.beginColumn, - prev, number(op, n, 3)); - break; - case REM: - n = jj_consume_token(REM); - result = LexicalUnitImpl.createREM(n.beginLine, n.beginColumn, - prev, number(op, n, 3)); - break; - case EXS: - n = jj_consume_token(EXS); - result = LexicalUnitImpl.createEXS(n.beginLine, n.beginColumn, - prev, number(op, n, 2)); - break; - case DEG: - n = jj_consume_token(DEG); - result = LexicalUnitImpl.createDEG(n.beginLine, n.beginColumn, - prev, number(op, n, 3)); - break; - case RAD: - n = jj_consume_token(RAD); - result = LexicalUnitImpl.createRAD(n.beginLine, n.beginColumn, - prev, number(op, n, 3)); - break; - case GRAD: - n = jj_consume_token(GRAD); - result = LexicalUnitImpl.createGRAD(n.beginLine, n.beginColumn, - prev, number(op, n, 3)); - break; - case SECOND: - n = jj_consume_token(SECOND); - result = LexicalUnitImpl.createS(n.beginLine, n.beginColumn, - prev, number(op, n, 1)); - break; - case MS: - n = jj_consume_token(MS); - result = LexicalUnitImpl.createMS(n.beginLine, n.beginColumn, - prev, number(op, n, 2)); - break; - case HZ: - n = jj_consume_token(HZ); - result = LexicalUnitImpl.createHZ(n.beginLine, n.beginColumn, - prev, number(op, n, 2)); - break; - case KHZ: - n = jj_consume_token(KHZ); - result = LexicalUnitImpl.createKHZ(n.beginLine, n.beginColumn, - prev, number(op, n, 3)); - break; - case DIMEN: - n = jj_consume_token(DIMEN); - s = n.image; - int i = 0; - while (i < s.length() - && (Character.isDigit(s.charAt(i)) || (s.charAt(i) == '.'))) { - i++; - } +/** + * @exception ParseException exception during the parse + */ + final public char unaryOperator() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case MINUS: + jj_consume_token(MINUS); + {if (true) return '-';} + break; + case PLUS: + jj_consume_token(PLUS); + {if (true) return '+';} + break; + default: + jj_la1[242] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } - result = LexicalUnitImpl.createDimen(n.beginLine, - n.beginColumn, prev, number(op, n, s.length() - i), - s.substring(i)); - break; - case FUNCTION: - result = function(op, prev); - break; - default: - jj_la1[243] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); +/** + * @exception ParseException exception during the parse + */ + final public LexicalUnitImpl term(LexicalUnitImpl prev) throws ParseException { + LexicalUnitImpl result = null; + Token n = null; + char op = ' '; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case MINUS: + case DOT: + case TO: + case THROUGH: + case FROM: + case STRING: + case IDENT: + case NUMBER: + case URL: + case PERCENTAGE: + case PT: + case MM: + case CM: + case PC: + case IN: + case PX: + case EMS: + case LEM: + case REM: + case EXS: + case DEG: + case RAD: + case GRAD: + case MS: + case SECOND: + case HZ: + case KHZ: + case DIMEN: + case HASH: + case UNICODERANGE: + case FUNCTION: + result = nonVariableTerm(prev); + break; + case VARIABLE: + result = variableTerm(prev); + break; + default: + jj_la1[243] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + {if (true) return result;} + throw new Error("Missing return statement in function"); + } + + final public LexicalUnitImpl variableTerm(LexicalUnitImpl prev) throws ParseException { + LexicalUnitImpl result = null; + String varName = ""; + varName = variableName(); + result = LexicalUnitImpl.createVariable(token.beginLine, token.beginColumn, + prev, varName); {if (true) return result;} + throw new Error("Missing return statement in function"); + } + + final public LexicalUnitImpl nonVariableTerm(LexicalUnitImpl prev) throws ParseException { +LexicalUnitImpl result = null; + Token n = null; + char op = ' '; + String varName; + String s = ""; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case MINUS: + case NUMBER: + case PERCENTAGE: + case PT: + case MM: + case CM: + case PC: + case IN: + case PX: + case EMS: + case LEM: + case REM: + case EXS: + case DEG: + case RAD: + case GRAD: + case MS: + case SECOND: + case HZ: + case KHZ: + case DIMEN: + case FUNCTION: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case MINUS: + op = unaryOperator(); + break; + default: + jj_la1[244] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NUMBER: + n = jj_consume_token(NUMBER); + result = LexicalUnitImpl.createNumber(n.beginLine, n.beginColumn, + prev, number(op, n, 0)); + break; + case PERCENTAGE: + n = jj_consume_token(PERCENTAGE); + result = LexicalUnitImpl.createPercentage(n.beginLine, n.beginColumn, + prev, number(op, n, 1)); + break; + case PT: + n = jj_consume_token(PT); + result = LexicalUnitImpl.createPT(n.beginLine, n.beginColumn, + prev, number(op, n, 2)); + break; + case CM: + n = jj_consume_token(CM); + result = LexicalUnitImpl.createCM(n.beginLine, n.beginColumn, + prev, number(op, n, 2)); + break; + case MM: + n = jj_consume_token(MM); + result = LexicalUnitImpl.createMM(n.beginLine, n.beginColumn, + prev, number(op, n, 2)); + break; + case PC: + n = jj_consume_token(PC); + result = LexicalUnitImpl.createPC(n.beginLine, n.beginColumn, + prev, number(op, n, 2)); + break; + case IN: + n = jj_consume_token(IN); + result = LexicalUnitImpl.createIN(n.beginLine, n.beginColumn, + prev, number(op, n, 2)); + break; + case PX: + n = jj_consume_token(PX); + result = LexicalUnitImpl.createPX(n.beginLine, n.beginColumn, + prev, number(op, n, 2)); + break; + case EMS: + n = jj_consume_token(EMS); + result = LexicalUnitImpl.createEMS(n.beginLine, n.beginColumn, + prev, number(op, n, 2)); + break; + case LEM: + n = jj_consume_token(LEM); + result = LexicalUnitImpl.createLEM(n.beginLine, n.beginColumn, + prev, number(op, n, 3)); + break; + case REM: + n = jj_consume_token(REM); + result = LexicalUnitImpl.createREM(n.beginLine, n.beginColumn, + prev, number(op, n, 3)); + break; + case EXS: + n = jj_consume_token(EXS); + result = LexicalUnitImpl.createEXS(n.beginLine, n.beginColumn, + prev, number(op, n, 2)); + break; + case DEG: + n = jj_consume_token(DEG); + result = LexicalUnitImpl.createDEG(n.beginLine, n.beginColumn, + prev, number(op, n, 3)); + break; + case RAD: + n = jj_consume_token(RAD); + result = LexicalUnitImpl.createRAD(n.beginLine, n.beginColumn, + prev, number(op, n, 3)); + break; + case GRAD: + n = jj_consume_token(GRAD); + result = LexicalUnitImpl.createGRAD(n.beginLine, n.beginColumn, + prev, number(op, n, 3)); + break; + case SECOND: + n = jj_consume_token(SECOND); + result = LexicalUnitImpl.createS(n.beginLine, n.beginColumn, + prev, number(op, n, 1)); + break; + case MS: + n = jj_consume_token(MS); + result = LexicalUnitImpl.createMS(n.beginLine, n.beginColumn, + prev, number(op, n, 2)); + break; + case HZ: + n = jj_consume_token(HZ); + result = LexicalUnitImpl.createHZ(n.beginLine, n.beginColumn, + prev, number(op, n, 2)); + break; + case KHZ: + n = jj_consume_token(KHZ); + result = LexicalUnitImpl.createKHZ(n.beginLine, n.beginColumn, + prev, number(op, n, 3)); + break; + case DIMEN: + n = jj_consume_token(DIMEN); + s = n.image; + int i = 0; + while (i < s.length() + && (Character.isDigit(s.charAt(i)) || (s.charAt(i) == '.'))) { + i++; } - break; + + result = LexicalUnitImpl.createDimen(n.beginLine, n.beginColumn, prev, + number(op,n,s.length()-i), + s.substring(i)); + break; + case FUNCTION: + result = function(op, prev); + break; + default: + jj_la1[245] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + case DOT: + case TO: + case THROUGH: + case FROM: + case STRING: + case IDENT: + case URL: + case HASH: + case UNICODERANGE: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case STRING: + n = jj_consume_token(STRING); + result = + LexicalUnitImpl.createString(n.beginLine, n.beginColumn, prev, + convertStringIndex(n.image, 1, + n.image.length() -1)); + break; + case DOT: + case TO: + case THROUGH: + case FROM: + case IDENT: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { case DOT: + jj_consume_token(DOT); + s+="."; + break; + default: + jj_la1[246] = jj_gen; + ; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENT: + n = jj_consume_token(IDENT); + break; case TO: + n = jj_consume_token(TO); + break; case THROUGH: + n = jj_consume_token(THROUGH); + break; case FROM: - case STRING: - case IDENT: - case URL: - case HASH: - case UNICODERANGE: - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case STRING: - n = jj_consume_token(STRING); - result = LexicalUnitImpl.createString(n.beginLine, - n.beginColumn, prev, - convertStringIndex(n.image, 1, n.image.length() - 1)); - break; - case DOT: - case TO: - case THROUGH: - case FROM: - case IDENT: - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case DOT: - jj_consume_token(DOT); - s += "."; - break; - default: - jj_la1[244] = jj_gen; - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENT: - n = jj_consume_token(IDENT); - break; - case TO: - n = jj_consume_token(TO); - break; - case THROUGH: - n = jj_consume_token(THROUGH); - break; - case FROM: - n = jj_consume_token(FROM); - break; - default: - jj_la1[245] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - s += convertIdent(n.image); - if ("inherit".equals(s)) { - result = LexicalUnitImpl.createInherit(n.beginLine, - n.beginColumn, prev); - } else { - result = LexicalUnitImpl.createIdent(n.beginLine, - n.beginColumn, prev, convertIdent(n.image)); - } - - /* - * / Auto correction code used in the CSS Validator but must not - * be used by a conformant CSS2 parser. Common error : H1 { - * color : black background : white } - * - * Token t = getToken(1); Token semicolon = new Token(); - * semicolon.kind = SEMICOLON; semicolon.image = ";"; if (t.kind - * == COLON) { // @@SEEME. (generate a warning?) // @@SEEME if - * expression is a single ident, generate an error ? - * rejectToken(semicolon); - * - * result = prev; } / - */ - - break; - case HASH: - result = hexcolor(prev); - break; - case URL: - result = url(prev); - break; - case UNICODERANGE: - result = unicode(prev); - break; - default: - jj_la1[246] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - break; + n = jj_consume_token(FROM); + break; default: - jj_la1[247] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - label_167: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[248] = jj_gen; - break label_167; - } - jj_consume_token(S); - } - { - if (true) { - return result; - } - } - throw new Error("Missing return statement in function"); - } + jj_la1[247] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + s += convertIdent(n.image); + if ("inherit".equals(s)) { + result = LexicalUnitImpl.createInherit(n.beginLine, n.beginColumn, + prev); + } else { + result = LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn, + prev, convertIdent(n.image)); + } + + /* / + Auto correction code used in the CSS Validator but must not + be used by a conformant CSS2 parser. + * Common error : + * H1 { + * color : black + * background : white + * } + * + Token t = getToken(1); + Token semicolon = new Token(); + semicolon.kind = SEMICOLON; + semicolon.image = ";"; + if (t.kind == COLON) { + // @@SEEME. (generate a warning?) + // @@SEEME if expression is a single ident, + generate an error ? + rejectToken(semicolon); + + result = prev; + } + / */ + + break; + case HASH: + result = hexcolor(prev); + break; + case URL: + result = url(prev); + break; + case UNICODERANGE: + result = unicode(prev); + break; + default: + jj_la1[248] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_la1[249] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + label_167: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[250] = jj_gen; + break label_167; + } + jj_consume_token(S); + } + {if (true) return result;} + throw new Error("Missing return statement in function"); + } - /** - * Handle all CSS2 functions. - * - * @exception ParseException - * exception during the parse - */ - final public LexicalUnitImpl function(char operator, LexicalUnitImpl prev) - throws ParseException { - Token n; - LexicalUnit params = null; - n = jj_consume_token(FUNCTION); - label_168: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[249] = jj_gen; - break label_168; - } - jj_consume_token(S); - } +/** + * Handle all CSS2 functions. + * @exception ParseException exception during the parse + */ + final public LexicalUnitImpl function(char operator, LexicalUnitImpl prev) throws ParseException { + Token n; + LexicalUnit params = null; + n = jj_consume_token(FUNCTION); + label_168: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[251] = jj_gen; + break label_168; + } + jj_consume_token(S); + } String fname = convertIdent(n.image); - if ("alpha(".equals(fname)) { + if("alpha(".equals(fname)){ String body = skipStatementUntilSemiColon(); - { - if (true) { - return LexicalUnitImpl.createIdent(n.beginLine, - n.beginColumn, null, "alpha(" + body); - } - } - } else if ("expression(".equals(fname)) { + {if (true) return LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn, + null, "alpha("+body);} + }else if("expression(".equals(fname)){ String body = skipStatementUntilSemiColon(); - { - if (true) { - return LexicalUnitImpl.createIdent(n.beginLine, - n.beginColumn, null, "expression(" + body); - } - } - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case MINUS: - case DOT: - case TO: - case THROUGH: - case FROM: - case STRING: - case IDENT: - case NUMBER: - case URL: - case VARIABLE: - case PERCENTAGE: - case PT: - case MM: - case CM: - case PC: - case IN: - case PX: - case EMS: - case LEM: - case REM: - case EXS: - case DEG: - case RAD: - case GRAD: - case MS: - case SECOND: - case HZ: - case KHZ: - case DIMEN: - case HASH: - case UNICODERANGE: - case FUNCTION: - params = expr(); - break; - default: - jj_la1[250] = jj_gen; - ; - } - jj_consume_token(RPARAN); + {if (true) return LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn, + null, "expression("+body);} + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case MINUS: + case DOT: + case TO: + case THROUGH: + case FROM: + case STRING: + case IDENT: + case NUMBER: + case URL: + case VARIABLE: + case PERCENTAGE: + case PT: + case MM: + case CM: + case PC: + case IN: + case PX: + case EMS: + case LEM: + case REM: + case EXS: + case DEG: + case RAD: + case GRAD: + case MS: + case SECOND: + case HZ: + case KHZ: + case DIMEN: + case HASH: + case UNICODERANGE: + case FUNCTION: + params = expr(); + break; + default: + jj_la1[252] = jj_gen; + ; + } + jj_consume_token(RPARAN); if (operator != ' ') { - { - if (true) { - throw new CSSParseException( - "invalid operator before a function.", getLocator()); - } - } + {if (true) throw new CSSParseException("invalid operator before a function.", + getLocator());} } String f = convertIdent(n.image); LexicalUnitImpl l = (LexicalUnitImpl) params; @@ -5871,38 +5859,32 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { int i = 0; while (loop && l != null && i < 5) { switch (i) { - case 0: - case 2: - case 4: - if ((l.getLexicalUnitType() != LexicalUnit.SAC_INTEGER) + case 0: + case 2: + case 4: + if ((l.getLexicalUnitType() != LexicalUnit.SAC_INTEGER) && (l.getLexicalUnitType() != LexicalUnit.SAC_PERCENTAGE)) { - loop = false; - } - break; - case 1: - case 3: - if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) { - loop = false; - } - break; - default: { - if (true) { - throw new ParseException("implementation error"); - } - } + loop = false; + } + break; + case 1: + case 3: + if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) { + loop = false; + } + break; + default: + {if (true) throw new ParseException("implementation error");} } if (loop) { - l = l.getNextLexicalUnit(); - i++; + l = (LexicalUnitImpl) l.getNextLexicalUnit(); + i ++; } } if ((i == 5) && loop && (l == null)) { - { - if (true) { - return LexicalUnitImpl.createRGBColor(n.beginLine, - n.beginColumn, prev, params); - } - } + {if (true) return LexicalUnitImpl.createRGBColor(n.beginLine, + n.beginColumn, + prev, params);} } else { if (errorHandler != null) { String errorText; @@ -5910,63 +5892,54 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { if (i < 5) { if (params == null) { loc = new LocatorImpl(this, n.beginLine, - n.beginColumn - 1); + n.beginColumn-1); errorText = "not enough parameters."; } else if (l == null) { loc = new LocatorImpl(this, n.beginLine, - n.beginColumn - 1); + n.beginColumn-1); errorText = "not enough parameters: " - + params.toString(); + + params.toString(); } else { loc = new LocatorImpl(this, l.getLineNumber(), - l.getColumnNumber()); - errorText = "invalid parameter: " + l.toString(); + l.getColumnNumber()); + errorText = "invalid parameter: " + + l.toString(); } } else { loc = new LocatorImpl(this, l.getLineNumber(), - l.getColumnNumber()); - errorText = "too many parameters: " + l.toString(); + l.getColumnNumber()); + errorText = "too many parameters: " + + l.toString(); } errorHandler.error(new CSSParseException(errorText, loc)); } - { - if (true) { - throw new JumpException(); - } - } + {if (true) throw new JumpException();} } } else if ("counter".equals(f)) { int i = 0; while (loop && l != null && i < 3) { switch (i) { - case 0: - case 2: - if (l.getLexicalUnitType() != LexicalUnit.SAC_IDENT) { - loop = false; - } - break; - case 1: - if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) { - loop = false; - } - break; - default: { - if (true) { - throw new ParseException("implementation error"); - } - } + case 0: + case 2: + if (l.getLexicalUnitType() != LexicalUnit.SAC_IDENT) { + loop = false; + } + break; + case 1: + if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) { + loop = false; + } + break; + default: + {if (true) throw new ParseException("implementation error");} } - l = l.getNextLexicalUnit(); - i++; + l = (LexicalUnitImpl) l.getNextLexicalUnit(); + i ++; } if (((i == 1) || (i == 3)) && loop && (l == null)) { - { - if (true) { - return LexicalUnitImpl.createCounter(n.beginLine, - n.beginColumn, prev, params); - } - } + {if (true) return LexicalUnitImpl.createCounter(n.beginLine, n.beginColumn, + prev, params);} } } else if ("counters(".equals(f)) { @@ -5974,2650 +5947,1943 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { int i = 0; while (loop && l != null && i < 5) { switch (i) { - case 0: - case 4: - if (l.getLexicalUnitType() != LexicalUnit.SAC_IDENT) { - loop = false; - } - break; - case 2: - if (l.getLexicalUnitType() != LexicalUnit.SAC_STRING_VALUE) { - loop = false; - } - break; - case 1: - case 3: - if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) { - loop = false; - } - break; - default: { - if (true) { - throw new ParseException("implementation error"); - } - } + case 0: + case 4: + if (l.getLexicalUnitType() != LexicalUnit.SAC_IDENT) { + loop = false; + } + break; + case 2: + if (l.getLexicalUnitType() != LexicalUnit.SAC_STRING_VALUE) { + loop = false; + } + break; + case 1: + case 3: + if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) { + loop = false; + } + break; + default: + {if (true) throw new ParseException("implementation error");} } - l = l.getNextLexicalUnit(); - i++; + l = (LexicalUnitImpl) l.getNextLexicalUnit(); + i ++; } if (((i == 3) || (i == 5)) && loop && (l == null)) { - { - if (true) { - return LexicalUnitImpl.createCounters(n.beginLine, - n.beginColumn, prev, params); - } - } + {if (true) return LexicalUnitImpl.createCounters(n.beginLine, n.beginColumn, + prev, params);} } } else if ("attr(".equals(f)) { - if ((l != null) && (l.getNextLexicalUnit() == null) - && (l.getLexicalUnitType() == LexicalUnit.SAC_IDENT)) { - { - if (true) { - return LexicalUnitImpl.createAttr(l.getLineNumber(), - l.getColumnNumber(), prev, l.getStringValue()); - } - } + if ((l != null) + && (l.getNextLexicalUnit() == null) + && (l.getLexicalUnitType() == LexicalUnit.SAC_IDENT)) { + {if (true) return LexicalUnitImpl.createAttr(l.getLineNumber(), + l.getColumnNumber(), + prev, l.getStringValue());} } } else if ("rect(".equals(f)) { int i = 0; while (loop && l != null && i < 7) { switch (i) { - case 0: - case 2: - case 4: - case 6: - switch (l.getLexicalUnitType()) { - case LexicalUnit.SAC_INTEGER: - if (l.getIntegerValue() != 0) { + case 0: + case 2: + case 4: + case 6: + switch (l.getLexicalUnitType()) { + case LexicalUnit.SAC_INTEGER: + if (l.getIntegerValue() != 0) { + loop = false; + } + break; + case LexicalUnit.SAC_IDENT: + if (!l.getStringValue().equals("auto")) { + loop = false; + } + break; + case LexicalUnit.SAC_EM: + case LexicalUnit.SAC_EX: + case LexicalUnit.SAC_PIXEL: + case LexicalUnit.SAC_CENTIMETER: + case LexicalUnit.SAC_MILLIMETER: + case LexicalUnit.SAC_INCH: + case LexicalUnit.SAC_POINT: + case LexicalUnit.SAC_PICA: + // nothing + break; + default: loop = false; } break; - case LexicalUnit.SAC_IDENT: - if (!l.getStringValue().equals("auto")) { + case 1: + case 3: + case 5: + if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) { loop = false; } break; - case LexicalUnit.SAC_EM: - case LexicalUnit.SAC_EX: - case LexicalUnit.SAC_PIXEL: - case LexicalUnit.SAC_CENTIMETER: - case LexicalUnit.SAC_MILLIMETER: - case LexicalUnit.SAC_INCH: - case LexicalUnit.SAC_POINT: - case LexicalUnit.SAC_PICA: - // nothing - break; default: - loop = false; - } - break; - case 1: - case 3: - case 5: - if (l.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) { - loop = false; - } - break; - default: { - if (true) { - throw new ParseException("implementation error"); - } + {if (true) throw new ParseException("implementation error");} } - } - l = l.getNextLexicalUnit(); - i++; + l = (LexicalUnitImpl) l.getNextLexicalUnit(); + i ++; } if ((i == 7) && loop && (l == null)) { - { - if (true) { - return LexicalUnitImpl.createRect(n.beginLine, - n.beginColumn, prev, params); - } - } - } - } - { - if (true) { - return LexicalUnitImpl.createFunction(n.beginLine, - n.beginColumn, prev, f.substring(0, f.length() - 1), - params); - } - } - throw new Error("Missing return statement in function"); - } - - final public LexicalUnitImpl unicode(LexicalUnitImpl prev) - throws ParseException { - Token n; - n = jj_consume_token(UNICODERANGE); - LexicalUnitImpl params = null; - String s = n.image.substring(2); - int index = s.indexOf('-'); - if (index == -1) { - params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn, - params, Integer.parseInt(s, 16)); - } else { - String s1 = s.substring(0, index); - String s2 = s.substring(index); - - params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn, - params, Integer.parseInt(s1, 16)); - params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn, - params, Integer.parseInt(s2, 16)); - } - - { - if (true) { - return LexicalUnitImpl.createUnicodeRange(n.beginLine, - n.beginColumn, prev, params); - } - } - throw new Error("Missing return statement in function"); - } - - final public LexicalUnitImpl url(LexicalUnitImpl prev) - throws ParseException { - Token n; - n = jj_consume_token(URL); - String urlname = n.image.substring(4, n.image.length() - 1).trim(); - { - if (true) { - return LexicalUnitImpl.createURL(n.beginLine, n.beginColumn, - prev, urlname); - } - } - throw new Error("Missing return statement in function"); - } - - /** - * @exception ParseException - * exception during the parse - */ - final public LexicalUnitImpl hexcolor(LexicalUnitImpl prev) - throws ParseException { - Token n; - n = jj_consume_token(HASH); - int r; - LexicalUnitImpl first, params = null; - String s = n.image.substring(1); - - if (s.length() != 3 && s.length() != 6) { - first = null; - { - if (true) { - throw new CSSParseException( - "invalid hexadecimal notation for RGB: " + s, - getLocator()); - } - } - } - { - if (true) { - return LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn, - prev, n.image); - } - } - throw new Error("Missing return statement in function"); - } - - float number(char operator, Token n, int lengthUnit) throws ParseException { - String image = n.image; - float f = 0; - - if (lengthUnit != 0) { - image = image.substring(0, image.length() - lengthUnit); - } - f = Float.valueOf(image).floatValue(); - return (operator == '-') ? -f : f; - } - - String skipStatementUntilSemiColon() throws ParseException { - int[] semicolon = { SEMICOLON }; - return skipStatementUntil(semicolon); - } - - String skipStatementUntilLeftBrace() throws ParseException { - int[] lBrace = { LBRACE }; - return skipStatementUntil(lBrace); - } - - String skipStatementUntilMatchingRightParan() throws ParseException { - int[] leftTokens = { LPARAN, FUNCTION }; // a FUNCTION also contains "(" - int[] rightTokens = { RPARAN }; - StringBuffer s = new StringBuffer(); - int difference = 1; - Token tok; - while (difference != 0) { - tok = getToken(1); - if (tok.kind == EOF) { - return null; - } - for (int sym : leftTokens) { - if (tok.kind == sym) { - difference++; - } - } - for (int sym : rightTokens) { - if (tok.kind == sym) { - difference--; - } - } - if (difference != 0) { - if (tok.image != null) { - s.append(tok.image); - } - getNextToken(); - } - } - return s.toString().trim(); - } + {if (true) return LexicalUnitImpl.createRect(n.beginLine, n.beginColumn, + prev, params);} + } + } + {if (true) return LexicalUnitImpl.createFunction(n.beginLine, n.beginColumn, prev, + f.substring(0, + f.length() -1), + params);} + throw new Error("Missing return statement in function"); + } + + final public LexicalUnitImpl unicode(LexicalUnitImpl prev) throws ParseException { + Token n; + n = jj_consume_token(UNICODERANGE); + LexicalUnitImpl params = null; + String s = n.image.substring(2); + int index = s.indexOf('-'); + if (index == -1) { + params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn, + params, Integer.parseInt(s, 16)); + } else { + String s1 = s.substring(0, index); + String s2 = s.substring(index); + + params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn, + params, Integer.parseInt(s1, 16)); + params = LexicalUnitImpl.createInteger(n.beginLine, n.beginColumn, + params, Integer.parseInt(s2, 16)); + } + + {if (true) return LexicalUnitImpl.createUnicodeRange(n.beginLine, n.beginColumn, + prev, params);} + throw new Error("Missing return statement in function"); + } + + final public LexicalUnitImpl url(LexicalUnitImpl prev) throws ParseException { + Token n; + n = jj_consume_token(URL); + String urlname = n.image.substring(4, n.image.length()-1).trim(); + {if (true) return LexicalUnitImpl.createURL(n.beginLine, n.beginColumn, prev, urlname);} + throw new Error("Missing return statement in function"); + } - String skipStatementUntil(int[] symbols) throws ParseException { - StringBuffer s = new StringBuffer(); - boolean stop = false; - Token tok; - while (!stop) { - tok = getToken(1); - if (tok.kind == EOF) { - return null; - } - for (int sym : symbols) { - if (tok.kind == sym) { - stop = true; - break; - } - } - if (!stop) { - if (tok.image != null) { - s.append(tok.image); - } - getNextToken(); +/** + * @exception ParseException exception during the parse + */ + final public LexicalUnitImpl hexcolor(LexicalUnitImpl prev) throws ParseException { + Token n; + n = jj_consume_token(HASH); + int r; + LexicalUnitImpl first, params = null; + String s = n.image.substring(1); + + if(s.length()!=3 && s.length()!=6) { + first = null; + {if (true) throw new CSSParseException("invalid hexadecimal notation for RGB: " + s, + getLocator());} + } + {if (true) return LexicalUnitImpl.createIdent(n.beginLine, n.beginColumn, + prev, n.image);} + throw new Error("Missing return statement in function"); + } + + float number(char operator, Token n, int lengthUnit) throws ParseException { + String image = n.image; + float f = 0; + + if (lengthUnit != 0) { + image = image.substring(0, image.length() - lengthUnit); + } + f = Float.valueOf(image).floatValue(); + return (operator == '-')? -f: f; + } + + String skipStatementUntilSemiColon() throws ParseException { + int[] semicolon = {SEMICOLON}; + return skipStatementUntil(semicolon); + } + + String skipStatementUntilLeftBrace() throws ParseException { + int[] lBrace = {LBRACE}; + return skipStatementUntil(lBrace); + } + + String skipStatementUntilMatchingRightParan() throws ParseException { + int[] leftTokens = {LPARAN, FUNCTION}; // a FUNCTION also contains "(" + int[] rightTokens = {RPARAN}; + StringBuffer s = new StringBuffer(); + int difference = 1; + Token tok; + while(difference != 0){ + tok = getToken(1); + if(tok.kind == EOF) { + return null; + } + for(int sym : leftTokens){ + if(tok.kind == sym){ + difference++; + } + } + for(int sym : rightTokens){ + if(tok.kind == sym){ + difference--; + } + } + if(difference != 0){ + if (tok.image != null) { + s.append(tok.image); } + getNextToken(); } - return s.toString().trim(); } + return s.toString().trim(); + } - String skipStatement() throws ParseException { - StringBuffer s = new StringBuffer(); - Token tok = getToken(0); - if (tok.image != null) { - s.append(tok.image); - } - while (true) { - tok = getToken(1); - if (tok.kind == EOF) { - return null; - } - s.append(tok.image); - if (tok.kind == LBRACE) { - getNextToken(); - s.append(skip_to_matching_brace()); - getNextToken(); - tok = getToken(1); - break; - } else if (tok.kind == RBRACE) { - getNextToken(); - tok = getToken(1); - break; - } else if (tok.kind == SEMICOLON) { - getNextToken(); - tok = getToken(1); + String skipStatementUntil(int[] symbols) throws ParseException { + StringBuffer s = new StringBuffer(); + boolean found = false; + Token tok; + while(!found){ + tok = getToken(1); + for(int sym : symbols){ + if(tok.kind == sym){ + found = true; break; } - getNextToken(); } - - // skip white space - while (true) { - if (tok.kind != S) { - break; - } - tok = getNextToken(); - tok = getToken(1); + if(tok.kind == EOF) { + break; } - - return s.toString().trim(); - } - - String skip_to_matching_brace() throws ParseException { - StringBuffer s = new StringBuffer(); - Token tok; - int nesting = 1; - while (true) { - tok = getToken(1); - if (tok.kind == EOF) { - break; - } - s.append(tok.image); - if (tok.kind == LBRACE) { - nesting++; - } else if (tok.kind == RBRACE) { - nesting--; - if (nesting == 0) { - break; - } + if(!found){ + if (tok.image != null) { + s.append(tok.image); } getNextToken(); } - return s.toString(); - } - - String convertStringIndex(String s, int start, int len) - throws ParseException { - StringBuffer buf = new StringBuffer(len); - int index = start; - - while (index < len) { - char c = s.charAt(index); - if (c == '\u005c\u005c') { - if (++index < len) { - c = s.charAt(index); - switch (c) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - buf.append('\u005c\u005c'); - while (index < len) { - buf.append(s.charAt(index++)); - } - break; - case '\u005cn': - case '\u005cf': - break; - case '\u005cr': - if (index + 1 < len) { - if (s.charAt(index + 1) == '\u005cn') { - index++; - } - } - break; - default: - buf.append(c); - } - } else { - throw new CSSParseException("invalid string " + s, - getLocator()); - } - } else { - buf.append(c); - } - index++; - } - - return buf.toString(); - } - - String convertIdent(String s) throws ParseException { - return convertStringIndex(s, 0, s.length()); } + return found ? s.toString().trim() : null; + } - String convertString(String s) throws ParseException { - return convertStringIndex(s, 0, s.length()); + String skipStatement() throws ParseException { + StringBuffer s = new StringBuffer(); + Token tok = getToken(0); + if (tok.image != null) { + s.append(tok.image); } - - void comments() throws ParseException { - /* - * keeps only the multiple line comments, single line comments are - * skipped - */ - if (token.specialToken != null && token.specialToken.image != null - && token.specialToken.image.startsWith("/*")) { - Token tmp_t = token.specialToken; - while (tmp_t.specialToken != null) { - tmp_t = tmp_t.specialToken; - } - while (tmp_t != null) { - documentHandler.comment(tmp_t.image); - tmp_t = tmp_t.next; - } + while (true) { + tok = getToken(1); + if (tok.kind == EOF) { + return null; } - } - - void rejectToken(Token t) throws ParseException { - Token fakeToken = new Token(); - t.next = token; - fakeToken.next = t; - token = fakeToken; - } - - String skipAfterExpression() throws ParseException { - Token t = getToken(1); - StringBuffer s = new StringBuffer(); - s.append(getToken(0).image); - - while ((t.kind != RBRACE) && (t.kind != SEMICOLON) && (t.kind != EOF)) { - s.append(t.image); + s.append(tok.image); + if (tok.kind == LBRACE) { getNextToken(); - t = getToken(1); - } - - return s.toString(); - } - - /** - * The following functions are useful for a DOM CSS implementation only and - * are not part of the general CSS2 parser. - */ - // TODO required by original parser but not used by Vaadin? - final public void _parseRule() throws ParseException { - String ret = null; - label_169: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[251] = jj_gen; - break label_169; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IMPORT_SYM: - importDeclaration(); - break; - case DEBUG_SYM: - case WARN_SYM: - debuggingDirective(); - break; - case PLUS: - case PRECEDES: - case SIBLING: - case LBRACKET: - case ANY: - case PARENT: - case DOT: - case COLON: - case INTERPOLATION: - case IDENT: - case HASH: - styleRule(); - break; - case MEDIA_SYM: - media(); + s.append(skip_to_matching_brace()); + getNextToken(); + tok = getToken(1); break; - case PAGE_SYM: - page(); + } else if (tok.kind == RBRACE) { + getNextToken(); + tok = getToken(1); break; - case FONT_FACE_SYM: - fontFace(); + } else if (tok.kind == SEMICOLON) { + getNextToken(); + tok = getToken(1); break; - default: - jj_la1[252] = jj_gen; - ret = skipStatement(); - if ((ret == null) || (ret.length() == 0)) { - { - if (true) { - return; - } - } - } - if (ret.charAt(0) == '@') { - documentHandler.unrecognizedRule(ret); - } else { - { - if (true) { - throw new CSSParseException("unrecognize rule: " + ret, - getLocator()); - } - } - } } + getNextToken(); } - final public void _parseImportRule() throws ParseException { - label_170: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[253] = jj_gen; - break label_170; - } - jj_consume_token(S); + // skip white space + while (true) { + if (tok.kind != S) { + break; } - importDeclaration(); + tok = getNextToken(); + tok = getToken(1); } - final public void _parseMediaRule() throws ParseException { - label_171: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[254] = jj_gen; - break label_171; - } - jj_consume_token(S); - } - media(); - } + return s.toString().trim(); + } - final public void _parseDeclarationBlock() throws ParseException { - label_172: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; - break; - default: - jj_la1[255] = jj_gen; - break label_172; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - declaration(); + String skip_to_matching_brace() throws ParseException { + StringBuffer s = new StringBuffer(); + Token tok; + int nesting = 1; + while (true) { + tok = getToken(1); + if (tok.kind == EOF) { break; - default: - jj_la1[256] = jj_gen; - ; } - label_173: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - ; - break; - default: - jj_la1[257] = jj_gen; - break label_173; - } - jj_consume_token(SEMICOLON); - label_174: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; + s.append(tok.image); + if (tok.kind == LBRACE) { + nesting++; + } else if (tok.kind == RBRACE) { + nesting--; + if (nesting == 0) { + break; + } + } + getNextToken(); + } + return s.toString(); + } + + String convertStringIndex(String s, int start, int len) throws ParseException { + StringBuffer buf = new StringBuffer(len); + int index = start; + + while (index < len) { + char c = s.charAt(index); + if (c == '\u005c\u005c') { + if (++index < len) { + c = s.charAt(index); + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + buf.append('\u005c\u005c'); + while (index < len) { + buf.append(s.charAt(index++)); + } break; - default: - jj_la1[258] = jj_gen; - break label_174; - } - jj_consume_token(S); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTERPOLATION: - case IDENT: - declaration(); - break; - default: - jj_la1[259] = jj_gen; - ; - } - } - } - - final public ArrayList<String> _parseSelectors() throws ParseException { - ArrayList<String> p = null; - try { - label_175: while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case S: - ; + case '\u005cn': + case '\u005cf': break; - default: - jj_la1[260] = jj_gen; - break label_175; - } - jj_consume_token(S); - } - p = selectorList(); - { - if (true) { - return p; - } - } - } catch (ThrowedParseException e) { - { - if (true) { - throw (ParseException) e.e.fillInStackTrace(); - } - } - } - throw new Error("Missing return statement in function"); - } - - private boolean jj_2_1(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_1(); - } catch (LookaheadSuccess ls) { - return true; - } finally { - jj_save(0, xla); - } - } - - private boolean jj_2_2(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_2(); - } catch (LookaheadSuccess ls) { - return true; - } finally { - jj_save(1, xla); - } - } - - private boolean jj_2_3(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_3(); - } catch (LookaheadSuccess ls) { - return true; - } finally { - jj_save(2, xla); - } - } - - private boolean jj_2_4(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_4(); - } catch (LookaheadSuccess ls) { - return true; - } finally { - jj_save(3, xla); - } - } - - private boolean jj_2_5(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_5(); - } catch (LookaheadSuccess ls) { - return true; - } finally { - jj_save(4, xla); - } - } - - private boolean jj_2_6(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_6(); - } catch (LookaheadSuccess ls) { - return true; - } finally { - jj_save(5, xla); - } - } - - private boolean jj_2_7(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_7(); - } catch (LookaheadSuccess ls) { - return true; - } finally { - jj_save(6, xla); - } - } - - private boolean jj_2_8(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_8(); - } catch (LookaheadSuccess ls) { - return true; - } finally { - jj_save(7, xla); - } - } - - private boolean jj_2_9(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_9(); - } catch (LookaheadSuccess ls) { - return true; - } finally { - jj_save(8, xla); - } - } - - private boolean jj_3R_209() { - if (jj_scan_token(MINUS)) { - return true; - } - Token xsp; - if (jj_scan_token(1)) { - return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_188() { - if (jj_3R_210()) { - return true; - } - return false; - } - - private boolean jj_3R_208() { - if (jj_scan_token(PLUS)) { - return true; - } - Token xsp; - if (jj_scan_token(1)) { - return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_207() { - if (jj_scan_token(MOD)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_206() { - if (jj_scan_token(ANY)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_205() { - if (jj_scan_token(DIV)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_204() { - if (jj_scan_token(COMMA)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_185() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_204()) { - jj_scanpos = xsp; - if (jj_3R_205()) { - jj_scanpos = xsp; - if (jj_3R_206()) { - jj_scanpos = xsp; - if (jj_3R_207()) { - jj_scanpos = xsp; - if (jj_3R_208()) { - jj_scanpos = xsp; - if (jj_3R_209()) { - return true; - } - } - } - } - } - } - return false; - } - - private boolean jj_3R_212() { - if (jj_3R_211()) { - return true; - } - return false; - } - - private boolean jj_3R_211() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(18)) { - jj_scanpos = xsp; - if (jj_scan_token(22)) { - jj_scanpos = xsp; - if (jj_scan_token(23)) { - return true; - } - } - } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_191() { - if (jj_scan_token(S)) { - return true; - } - Token xsp; - xsp = jj_scanpos; - if (jj_3R_212()) { - jj_scanpos = xsp; - } - return false; - } - - private boolean jj_3R_210() { - if (jj_scan_token(GUARDED_SYM)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_176() { - if (jj_3R_186()) { - return true; - } - if (jj_scan_token(COLON)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - if (jj_3R_187()) { - return true; - } - xsp = jj_scanpos; - if (jj_3R_188()) { - jj_scanpos = xsp; - } - if (jj_3R_189()) { - return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_3R_189()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_190() { - if (jj_3R_211()) { - return true; - } - return false; - } - - private boolean jj_3R_177() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_190()) { - jj_scanpos = xsp; - if (jj_3R_191()) { - return true; - } - } - return false; - } - - private boolean jj_3R_194() { - if (jj_scan_token(VARIABLE)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(COLON)) { - return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_179() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_194()) { - jj_scanpos = xsp; - } - if (jj_scan_token(CONTAINS)) { - return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - if (true) { - jj_la = 0; - jj_scanpos = jj_lastpos; - return false; - } - return false; - } - - private boolean jj_3R_262() { - if (jj_scan_token(HASH)) { - return true; - } - return false; - } - - private boolean jj_3R_279() { - if (jj_scan_token(IDENT)) { - return true; - } - return false; - } - - private boolean jj_3R_280() { - if (jj_scan_token(FUNCTION)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - if (true) { - jj_la = 0; - jj_scanpos = jj_lastpos; - return false; - } - return false; - } - - private boolean jj_3R_278() { - if (jj_scan_token(COLON)) { - return true; - } - return false; - } - - private boolean jj_3R_265() { - if (jj_scan_token(COLON)) { - return true; - } - Token xsp; - xsp = jj_scanpos; - if (jj_3R_278()) { - jj_scanpos = xsp; - } - xsp = jj_scanpos; - if (jj_3R_279()) { - jj_scanpos = xsp; - if (jj_3R_280()) { - return true; - } - } - return false; - } - - private boolean jj_3_7() { - if (jj_3R_183()) { - return true; - } - return false; - } - - private boolean jj_3R_201() { - if (jj_scan_token(LBRACE)) { - return true; - } - return false; - } - - private boolean jj_3R_290() { - if (jj_scan_token(STRING)) { - return true; - } - return false; - } - - private boolean jj_3R_288() { - if (jj_scan_token(STARMATCH)) { - return true; - } - return false; - } - - private boolean jj_3R_287() { - if (jj_scan_token(DOLLARMATCH)) { - return true; - } - return false; - } - - private boolean jj_3R_289() { - if (jj_scan_token(IDENT)) { - return true; - } - return false; - } - - private boolean jj_3R_286() { - if (jj_scan_token(CARETMATCH)) { - return true; - } - return false; - } - - private boolean jj_3R_285() { - if (jj_scan_token(DASHMATCH)) { - return true; - } - return false; - } - - private boolean jj_3R_284() { - if (jj_scan_token(INCLUDES)) { - return true; - } - return false; - } - - private boolean jj_3R_270() { - if (jj_scan_token(INTERPOLATION)) { - return true; - } - return false; - } - - private boolean jj_3R_283() { - if (jj_scan_token(EQ)) { - return true; - } - return false; - } - - private boolean jj_3R_200() { - if (jj_3R_187()) { - return true; - } - return false; - } - - private boolean jj_3R_277() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_283()) { - jj_scanpos = xsp; - if (jj_3R_284()) { - jj_scanpos = xsp; - if (jj_3R_285()) { - jj_scanpos = xsp; - if (jj_3R_286()) { - jj_scanpos = xsp; - if (jj_3R_287()) { - jj_scanpos = xsp; - if (jj_3R_288()) { - return true; - } + case '\u005cr': + if (index + 1 < len) { + if (s.charAt(index + 1) == '\u005cn') { + index ++; } } + break; + default: + buf.append(c); } + } else { + throw new CSSParseException("invalid string " + s, getLocator()); } + } else { + buf.append(c); } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - xsp = jj_scanpos; - if (jj_3R_289()) { - jj_scanpos = xsp; - if (jj_3R_290()) { - return true; - } - } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3_6() { - if (jj_3R_182()) { - return true; - } - if (jj_scan_token(LBRACE)) { - return true; - } - return false; - } - - private boolean jj_3R_264() { - if (jj_scan_token(LBRACKET)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(IDENT)) { - return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - xsp = jj_scanpos; - if (jj_3R_277()) { - jj_scanpos = xsp; - } - if (jj_scan_token(RBRACKET)) { - return true; - } - return false; - } - - private boolean jj_3R_183() { - if (jj_3R_199()) { - return true; - } - if (jj_scan_token(COLON)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - xsp = jj_scanpos; - if (jj_3R_200()) { - jj_scanpos = xsp; - if (jj_3R_201()) { - return true; - } - } - return false; - } - - private boolean jj_3R_282() { - if (jj_scan_token(INTERPOLATION)) { - return true; - } - return false; - } - - private boolean jj_3R_268() { - if (jj_3R_187()) { - return true; - } - return false; - } - - private boolean jj_3R_248() { - if (jj_scan_token(PARENT)) { - return true; - } - return false; - } - - private boolean jj_3R_247() { - if (jj_scan_token(ANY)) { - return true; - } - return false; - } - - private boolean jj_3R_261() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_269()) { - jj_scanpos = xsp; - if (jj_3R_270()) { - return true; - } - } - return false; - } - - private boolean jj_3R_269() { - if (jj_scan_token(IDENT)) { - return true; - } - return false; - } - - private boolean jj_3R_213() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_246()) { - jj_scanpos = xsp; - if (jj_3R_247()) { - jj_scanpos = xsp; - if (jj_3R_248()) { - return true; - } - } - } - return false; - } - - private boolean jj_3R_246() { - Token xsp; - if (jj_3R_261()) { - return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_3R_261()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_254() { - if (jj_scan_token(FUNCTION)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - xsp = jj_scanpos; - if (jj_3R_268()) { - jj_scanpos = xsp; - } - if (jj_scan_token(RPARAN)) { - return true; - } - return false; - } - - private boolean jj_3R_180() { - if (jj_scan_token(COMMA)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_241() { - if (jj_3R_258()) { - return true; - } - return false; - } - - private boolean jj_3R_276() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_281()) { - jj_scanpos = xsp; - if (jj_3R_282()) { - return true; - } - } - return false; - } - - private boolean jj_3R_281() { - if (jj_scan_token(IDENT)) { - return true; - } - return false; - } - - private boolean jj_3R_240() { - if (jj_3R_257()) { - return true; - } - return false; - } - - private boolean jj_3R_239() { - if (jj_3R_256()) { - return true; - } - return false; - } - - private boolean jj_3_5() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_180()) { - jj_scanpos = xsp; - } - if (jj_3R_181()) { - return true; - } - return false; - } - - private boolean jj_3R_263() { - if (jj_scan_token(DOT)) { - return true; - } - Token xsp; - if (jj_3R_276()) { - return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_3R_276()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_252() { - if (jj_3R_265()) { - return true; - } - return false; - } - - private boolean jj_3R_275() { - if (jj_3R_265()) { - return true; - } - return false; - } - - private boolean jj_3R_273() { - if (jj_3R_263()) { - return true; - } - return false; - } - - private boolean jj_3R_250() { - if (jj_3R_263()) { - return true; - } - return false; - } - - private boolean jj_3R_251() { - if (jj_3R_264()) { - return true; - } - return false; + index++; } - private boolean jj_3R_274() { - if (jj_3R_264()) { - return true; - } - return false; - } + return buf.toString(); + } - private boolean jj_3R_255() { - if (jj_scan_token(DOT)) { - return true; - } - return false; - } + String convertIdent(String s) throws ParseException { + return convertStringIndex(s, 0, s.length()); + } - private boolean jj_3R_271() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_272()) { - jj_scanpos = xsp; - if (jj_3R_273()) { - jj_scanpos = xsp; - if (jj_3R_274()) { - jj_scanpos = xsp; - if (jj_3R_275()) { - return true; - } - } - } - } - return false; - } + String convertString(String s) throws ParseException { + return convertStringIndex(s, 0, s.length()); + } - private boolean jj_3R_272() { - if (jj_3R_262()) { - return true; + void comments() throws ParseException { + /*keeps only the multiple line comments, single line comments are skipped*/ + if (token.specialToken != null && token.specialToken.image!=null && token.specialToken.image.startsWith("/*")){ + Token tmp_t = token.specialToken; + while (tmp_t.specialToken != null) tmp_t = tmp_t.specialToken; + while (tmp_t != null) { + documentHandler.comment(tmp_t.image); + tmp_t = tmp_t.next; } - return false; } + } - private boolean jj_3R_238() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_255()) { - jj_scanpos = xsp; - } - xsp = jj_scanpos; - if (jj_scan_token(72)) { - jj_scanpos = xsp; - if (jj_scan_token(49)) { - jj_scanpos = xsp; - if (jj_scan_token(50)) { - jj_scanpos = xsp; - if (jj_scan_token(52)) { - return true; - } - } - } - } - return false; - } + void rejectToken(Token t) throws ParseException { + Token fakeToken = new Token(); + t.next = token; + fakeToken.next = t; + token = fakeToken; + } - private boolean jj_3R_237() { - if (jj_scan_token(STRING)) { - return true; - } - return false; - } + String skipAfterExpression() throws ParseException { + Token t = getToken(1); + StringBuffer s = new StringBuffer(); + s.append(getToken(0).image); - private boolean jj_3R_214() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_249()) { - jj_scanpos = xsp; - if (jj_3R_250()) { - jj_scanpos = xsp; - if (jj_3R_251()) { - jj_scanpos = xsp; - if (jj_3R_252()) { - return true; - } - } - } - } - return false; - } - - private boolean jj_3R_249() { - if (jj_3R_262()) { - return true; - } - return false; + while ((t.kind != RBRACE) && (t.kind != SEMICOLON) && (t.kind != EOF)) { + s.append(t.image); + getNextToken(); + t = getToken(1); } - private boolean jj_3R_236() { - if (jj_3R_254()) { - return true; - } - return false; - } + return s.toString(); + } - private boolean jj_3R_196() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_237()) { - jj_scanpos = xsp; - if (jj_3R_238()) { - jj_scanpos = xsp; - if (jj_3R_239()) { - jj_scanpos = xsp; - if (jj_3R_240()) { - jj_scanpos = xsp; - if (jj_3R_241()) { - return true; - } +/** + * The following functions are useful for a DOM CSS implementation only and are + * not part of the general CSS2 parser. + */ +// TODO required by original parser but not used by Vaadin? + final public void _parseRule() throws ParseException { + String ret = null; + label_169: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[253] = jj_gen; + break label_169; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IMPORT_SYM: + importDeclaration(); + break; + case DEBUG_SYM: + case WARN_SYM: + debuggingDirective(); + break; + case PLUS: + case PRECEDES: + case SIBLING: + case LBRACKET: + case ANY: + case PARENT: + case DOT: + case COLON: + case INTERPOLATION: + case IDENT: + case HASH: + styleRule(); + break; + case MEDIA_SYM: + media(); + break; + case PAGE_SYM: + page(); + break; + case FONT_FACE_SYM: + fontFace(); + break; + default: + jj_la1[254] = jj_gen; + ret = skipStatement(); + if ((ret == null) || (ret.length() == 0)) { + {if (true) return;} } - } - } - } - return false; - } - - private boolean jj_3R_193() { - Token xsp; - if (jj_3R_214()) { - return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_3R_214()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_192() { - if (jj_3R_213()) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_271()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_178() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_192()) { - jj_scanpos = xsp; - if (jj_3R_193()) { - return true; - } - } - return false; - } - - private boolean jj_3R_243() { - if (jj_3R_211()) { - return true; - } - if (jj_3R_178()) { - return true; - } - return false; - } - - private boolean jj_3R_235() { - if (jj_scan_token(DIMEN)) { - return true; - } - return false; - } - - private boolean jj_3R_234() { - if (jj_scan_token(KHZ)) { - return true; - } - return false; - } - - private boolean jj_3R_233() { - if (jj_scan_token(HZ)) { - return true; - } - return false; - } - - private boolean jj_3R_232() { - if (jj_scan_token(MS)) { - return true; - } - return false; - } - - private boolean jj_3R_231() { - if (jj_scan_token(SECOND)) { - return true; - } - return false; - } - - private boolean jj_3R_230() { - if (jj_scan_token(GRAD)) { - return true; - } - return false; - } - - private boolean jj_3R_229() { - if (jj_scan_token(RAD)) { - return true; - } - return false; - } - - private boolean jj_3R_228() { - if (jj_scan_token(DEG)) { - return true; - } - return false; - } - - private boolean jj_3R_227() { - if (jj_scan_token(EXS)) { - return true; - } - return false; - } - - private boolean jj_3R_226() { - if (jj_scan_token(REM)) { - return true; - } - return false; - } - - private boolean jj_3_2() { - if (jj_3R_177()) { - return true; - } - if (jj_3R_178()) { - return true; - } - return false; - } - - private boolean jj_3R_225() { - if (jj_scan_token(LEM)) { - return true; - } - return false; - } - - private boolean jj_3R_224() { - if (jj_scan_token(EMS)) { - return true; - } - return false; - } - - private boolean jj_3R_198() { - if (jj_scan_token(COMMA)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - if (jj_3R_197()) { - return true; - } - return false; - } - - private boolean jj_3R_242() { - if (jj_3R_178()) { - return true; - } - return false; - } - - private boolean jj_3R_223() { - if (jj_scan_token(PX)) { - return true; - } - return false; - } - - private boolean jj_3R_222() { - if (jj_scan_token(IN)) { - return true; - } - return false; - } - - private boolean jj_3R_197() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_242()) { - jj_scanpos = xsp; - if (jj_3R_243()) { - return true; - } - } - while (true) { - xsp = jj_scanpos; - if (jj_3_2()) { - jj_scanpos = xsp; - break; - } - } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_221() { - if (jj_scan_token(PC)) { - return true; - } - return false; - } - - private boolean jj_3R_220() { - if (jj_scan_token(MM)) { - return true; - } - return false; - } - - private boolean jj_3R_219() { - if (jj_scan_token(CM)) { - return true; - } - return false; - } - - private boolean jj_3R_218() { - if (jj_scan_token(PT)) { - return true; - } - return false; - } - - private boolean jj_3R_217() { - if (jj_scan_token(PERCENTAGE)) { - return true; - } - return false; - } - - private boolean jj_3R_203() { - if (jj_3R_245()) { - return true; - } - return false; - } - - private boolean jj_3_1() { - if (jj_3R_176()) { - return true; - } - return false; - } - - private boolean jj_3R_182() { - if (jj_3R_197()) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_198()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_216() { - if (jj_scan_token(NUMBER)) { - return true; - } - return false; - } - - private boolean jj_3R_215() { - if (jj_3R_253()) { - return true; - } - return false; - } - - private boolean jj_3R_195() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_215()) { - jj_scanpos = xsp; - } - xsp = jj_scanpos; - if (jj_3R_216()) { - jj_scanpos = xsp; - if (jj_3R_217()) { - jj_scanpos = xsp; - if (jj_3R_218()) { - jj_scanpos = xsp; - if (jj_3R_219()) { - jj_scanpos = xsp; - if (jj_3R_220()) { - jj_scanpos = xsp; - if (jj_3R_221()) { - jj_scanpos = xsp; - if (jj_3R_222()) { - jj_scanpos = xsp; - if (jj_3R_223()) { - jj_scanpos = xsp; - if (jj_3R_224()) { - jj_scanpos = xsp; - if (jj_3R_225()) { - jj_scanpos = xsp; - if (jj_3R_226()) { - jj_scanpos = xsp; - if (jj_3R_227()) { - jj_scanpos = xsp; - if (jj_3R_228()) { - jj_scanpos = xsp; - if (jj_3R_229()) { - jj_scanpos = xsp; - if (jj_3R_230()) { - jj_scanpos = xsp; - if (jj_3R_231()) { - jj_scanpos = xsp; - if (jj_3R_232()) { - jj_scanpos = xsp; - if (jj_3R_233()) { - jj_scanpos = xsp; - if (jj_3R_234()) { - jj_scanpos = xsp; - if (jj_3R_235()) { - jj_scanpos = xsp; - if (jj_3R_236()) { - return true; - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } + if (ret.charAt(0) == '@') { + documentHandler.unrecognizedRule(ret); + } else { + {if (true) throw new CSSParseException("unrecognize rule: " + ret, + getLocator());} } - } - } - } - return false; - } - - private boolean jj_3R_181() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_195()) { - jj_scanpos = xsp; - if (jj_3R_196()) { - return true; - } - } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_256() { - if (jj_scan_token(HASH)) { - return true; - } - return false; - } - - private boolean jj_3_4() { - if (jj_3R_179()) { - return true; - } - return false; - } - - private boolean jj_3R_245() { - if (jj_3R_186()) { - return true; - } - return false; - } - - private boolean jj_3R_257() { - if (jj_scan_token(URL)) { - return true; - } - return false; - } - - private boolean jj_3R_202() { - if (jj_3R_181()) { - return true; - } - return false; - } - - private boolean jj_3R_260() { - if (jj_scan_token(INTERPOLATION)) { - return true; - } - return false; - } - - private boolean jj_3R_184() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_202()) { - jj_scanpos = xsp; - if (jj_3R_203()) { - return true; - } - } - return false; - } - - private boolean jj_3_9() { - if (jj_3R_185()) { - return true; - } - return false; - } - - private boolean jj_3_3() { - if (jj_3R_176()) { - return true; - } - return false; - } - - private boolean jj_3R_267() { - if (jj_scan_token(PLUS)) { - return true; - } - return false; - } - - private boolean jj_3R_253() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_266()) { - jj_scanpos = xsp; - if (jj_3R_267()) { - return true; - } - } - return false; - } - - private boolean jj_3R_266() { - if (jj_scan_token(MINUS)) { - return true; - } - return false; - } - - private boolean jj_3R_258() { - if (jj_scan_token(UNICODERANGE)) { - return true; - } - return false; } + } + + final public void _parseImportRule() throws ParseException { + label_170: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[255] = jj_gen; + break label_170; + } + jj_consume_token(S); + } + importDeclaration(); + } + + final public void _parseMediaRule() throws ParseException { + label_171: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[256] = jj_gen; + break label_171; + } + jj_consume_token(S); + } + media(); + } + + final public void _parseDeclarationBlock() throws ParseException { + label_172: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[257] = jj_gen; + break label_172; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + declaration(); + break; + default: + jj_la1[258] = jj_gen; + ; + } + label_173: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case SEMICOLON: + ; + break; + default: + jj_la1[259] = jj_gen; + break label_173; + } + jj_consume_token(SEMICOLON); + label_174: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[260] = jj_gen; + break label_174; + } + jj_consume_token(S); + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTERPOLATION: + case IDENT: + declaration(); + break; + default: + jj_la1[261] = jj_gen; + ; + } + } + } + + final public ArrayList<String> _parseSelectors() throws ParseException { + ArrayList<String> p = null; + try { + label_175: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case S: + ; + break; + default: + jj_la1[262] = jj_gen; + break label_175; + } + jj_consume_token(S); + } + p = selectorList(); + {if (true) return p;} + } catch (ThrowedParseException e) { + {if (true) throw (ParseException) e.e.fillInStackTrace();} + } + throw new Error("Missing return statement in function"); + } + + void acceptMissingSemicolonBeforeRbrace(ParseException parseException) throws ParseException { + Token next = getToken(1); + if (next.kind != RBRACE && next.kind!=EOF) { + throw parseException; + } + } + + private boolean jj_2_1(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_1(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(0, xla); } + } + + private boolean jj_2_2(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_2(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(1, xla); } + } + + private boolean jj_2_3(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_3(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(2, xla); } + } + + private boolean jj_2_4(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_4(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(3, xla); } + } + + private boolean jj_2_5(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_5(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(4, xla); } + } + + private boolean jj_2_6(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_6(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(5, xla); } + } + + private boolean jj_2_7(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_7(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(6, xla); } + } + + private boolean jj_2_8(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_8(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(7, xla); } + } + + private boolean jj_2_9(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + try { return !jj_3_9(); } + catch(LookaheadSuccess ls) { return true; } + finally { jj_save(8, xla); } + } + + private boolean jj_3R_194() { + if (jj_scan_token(VARIABLE)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + if (jj_scan_token(COLON)) return true; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_179() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_194()) jj_scanpos = xsp; + if (jj_scan_token(CONTAINS)) return true; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + if (true) { jj_la = 0; jj_scanpos = jj_lastpos; return false;} + return false; + } + + private boolean jj_3R_212() { + if (jj_3R_211()) return true; + return false; + } + + private boolean jj_3R_211() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(18)) { + jj_scanpos = xsp; + if (jj_scan_token(22)) { + jj_scanpos = xsp; + if (jj_scan_token(23)) return true; + } + } + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_191() { + if (jj_scan_token(S)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_212()) jj_scanpos = xsp; + return false; + } + + private boolean jj_3R_176() { + if (jj_3R_186()) return true; + if (jj_scan_token(COLON)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + if (jj_3R_187()) return true; + xsp = jj_scanpos; + if (jj_3R_188()) jj_scanpos = xsp; + if (jj_3R_189()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3R_189()) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_190() { + if (jj_3R_211()) return true; + return false; + } + + private boolean jj_3R_177() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_190()) { + jj_scanpos = xsp; + if (jj_3R_191()) return true; + } + return false; + } + + private boolean jj_3R_262() { + if (jj_scan_token(HASH)) return true; + return false; + } + + private boolean jj_3_7() { + if (jj_3R_183()) return true; + return false; + } + + private boolean jj_3R_279() { + if (jj_scan_token(IDENT)) return true; + return false; + } + + private boolean jj_3R_280() { + if (jj_scan_token(FUNCTION)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + if (true) { jj_la = 0; jj_scanpos = jj_lastpos; return false;} + return false; + } + + private boolean jj_3R_201() { + if (jj_scan_token(LBRACE)) return true; + return false; + } + + private boolean jj_3R_278() { + if (jj_scan_token(COLON)) return true; + return false; + } + + private boolean jj_3R_200() { + if (jj_3R_187()) return true; + return false; + } + + private boolean jj_3R_265() { + if (jj_scan_token(COLON)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_278()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_279()) { + jj_scanpos = xsp; + if (jj_3R_280()) return true; + } + return false; + } + + private boolean jj_3_6() { + if (jj_3R_182()) return true; + if (jj_scan_token(LBRACE)) return true; + return false; + } + + private boolean jj_3R_183() { + if (jj_3R_199()) return true; + if (jj_scan_token(COLON)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + xsp = jj_scanpos; + if (jj_3R_200()) { + jj_scanpos = xsp; + if (jj_3R_201()) return true; + } + return false; + } + + private boolean jj_3R_268() { + if (jj_3R_187()) return true; + return false; + } + + private boolean jj_3R_254() { + if (jj_scan_token(FUNCTION)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + xsp = jj_scanpos; + if (jj_3R_268()) jj_scanpos = xsp; + if (jj_scan_token(RPARAN)) return true; + return false; + } + + private boolean jj_3R_241() { + if (jj_3R_258()) return true; + return false; + } + + private boolean jj_3R_240() { + if (jj_3R_257()) return true; + return false; + } + + private boolean jj_3R_239() { + if (jj_3R_256()) return true; + return false; + } + + private boolean jj_3R_290() { + if (jj_scan_token(STRING)) return true; + return false; + } + + private boolean jj_3R_288() { + if (jj_scan_token(STARMATCH)) return true; + return false; + } + + private boolean jj_3R_287() { + if (jj_scan_token(DOLLARMATCH)) return true; + return false; + } + + private boolean jj_3R_289() { + if (jj_scan_token(IDENT)) return true; + return false; + } + + private boolean jj_3R_286() { + if (jj_scan_token(CARETMATCH)) return true; + return false; + } + + private boolean jj_3R_285() { + if (jj_scan_token(DASHMATCH)) return true; + return false; + } + + private boolean jj_3R_284() { + if (jj_scan_token(INCLUDES)) return true; + return false; + } + + private boolean jj_3R_270() { + if (jj_scan_token(INTERPOLATION)) return true; + return false; + } + + private boolean jj_3R_283() { + if (jj_scan_token(EQ)) return true; + return false; + } + + private boolean jj_3R_277() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_283()) { + jj_scanpos = xsp; + if (jj_3R_284()) { + jj_scanpos = xsp; + if (jj_3R_285()) { + jj_scanpos = xsp; + if (jj_3R_286()) { + jj_scanpos = xsp; + if (jj_3R_287()) { + jj_scanpos = xsp; + if (jj_3R_288()) return true; + } + } + } + } + } + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + xsp = jj_scanpos; + if (jj_3R_289()) { + jj_scanpos = xsp; + if (jj_3R_290()) return true; + } + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_264() { + if (jj_scan_token(LBRACKET)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + if (jj_scan_token(IDENT)) return true; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + xsp = jj_scanpos; + if (jj_3R_277()) jj_scanpos = xsp; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + private boolean jj_3R_180() { + if (jj_scan_token(COMMA)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_282() { + if (jj_scan_token(INTERPOLATION)) return true; + return false; + } + + private boolean jj_3R_248() { + if (jj_scan_token(PARENT)) return true; + return false; + } + + private boolean jj_3R_247() { + if (jj_scan_token(ANY)) return true; + return false; + } + + private boolean jj_3R_255() { + if (jj_scan_token(DOT)) return true; + return false; + } + + private boolean jj_3R_238() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_255()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_scan_token(72)) { + jj_scanpos = xsp; + if (jj_scan_token(49)) { + jj_scanpos = xsp; + if (jj_scan_token(50)) { + jj_scanpos = xsp; + if (jj_scan_token(52)) return true; + } + } + } + return false; + } + + private boolean jj_3_5() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_180()) jj_scanpos = xsp; + if (jj_3R_181()) return true; + return false; + } + + private boolean jj_3R_261() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_269()) { + jj_scanpos = xsp; + if (jj_3R_270()) return true; + } + return false; + } + + private boolean jj_3R_269() { + if (jj_scan_token(IDENT)) return true; + return false; + } + + private boolean jj_3R_237() { + if (jj_scan_token(STRING)) return true; + return false; + } + + private boolean jj_3R_213() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_246()) { + jj_scanpos = xsp; + if (jj_3R_247()) { + jj_scanpos = xsp; + if (jj_3R_248()) return true; + } + } + return false; + } + + private boolean jj_3R_246() { + Token xsp; + if (jj_3R_261()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3R_261()) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_236() { + if (jj_3R_254()) return true; + return false; + } + + private boolean jj_3R_196() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_237()) { + jj_scanpos = xsp; + if (jj_3R_238()) { + jj_scanpos = xsp; + if (jj_3R_239()) { + jj_scanpos = xsp; + if (jj_3R_240()) { + jj_scanpos = xsp; + if (jj_3R_241()) return true; + } + } + } + } + return false; + } + + private boolean jj_3R_235() { + if (jj_scan_token(DIMEN)) return true; + return false; + } + + private boolean jj_3R_276() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_281()) { + jj_scanpos = xsp; + if (jj_3R_282()) return true; + } + return false; + } + + private boolean jj_3R_281() { + if (jj_scan_token(IDENT)) return true; + return false; + } + + private boolean jj_3R_234() { + if (jj_scan_token(KHZ)) return true; + return false; + } + + private boolean jj_3R_233() { + if (jj_scan_token(HZ)) return true; + return false; + } + + private boolean jj_3R_263() { + if (jj_scan_token(DOT)) return true; + Token xsp; + if (jj_3R_276()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3R_276()) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_232() { + if (jj_scan_token(MS)) return true; + return false; + } + + private boolean jj_3R_231() { + if (jj_scan_token(SECOND)) return true; + return false; + } + + private boolean jj_3R_230() { + if (jj_scan_token(GRAD)) return true; + return false; + } + + private boolean jj_3R_252() { + if (jj_3R_265()) return true; + return false; + } + + private boolean jj_3R_275() { + if (jj_3R_265()) return true; + return false; + } + + private boolean jj_3R_229() { + if (jj_scan_token(RAD)) return true; + return false; + } + + private boolean jj_3R_228() { + if (jj_scan_token(DEG)) return true; + return false; + } + + private boolean jj_3R_273() { + if (jj_3R_263()) return true; + return false; + } + + private boolean jj_3R_227() { + if (jj_scan_token(EXS)) return true; + return false; + } + + private boolean jj_3R_250() { + if (jj_3R_263()) return true; + return false; + } + + private boolean jj_3R_226() { + if (jj_scan_token(REM)) return true; + return false; + } + + private boolean jj_3R_225() { + if (jj_scan_token(LEM)) return true; + return false; + } + + private boolean jj_3R_224() { + if (jj_scan_token(EMS)) return true; + return false; + } + + private boolean jj_3R_223() { + if (jj_scan_token(PX)) return true; + return false; + } + + private boolean jj_3R_251() { + if (jj_3R_264()) return true; + return false; + } + + private boolean jj_3R_274() { + if (jj_3R_264()) return true; + return false; + } + + private boolean jj_3R_222() { + if (jj_scan_token(IN)) return true; + return false; + } + + private boolean jj_3R_271() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_272()) { + jj_scanpos = xsp; + if (jj_3R_273()) { + jj_scanpos = xsp; + if (jj_3R_274()) { + jj_scanpos = xsp; + if (jj_3R_275()) return true; + } + } + } + return false; + } + + private boolean jj_3R_272() { + if (jj_3R_262()) return true; + return false; + } + + private boolean jj_3R_221() { + if (jj_scan_token(PC)) return true; + return false; + } + + private boolean jj_3R_214() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_249()) { + jj_scanpos = xsp; + if (jj_3R_250()) { + jj_scanpos = xsp; + if (jj_3R_251()) { + jj_scanpos = xsp; + if (jj_3R_252()) return true; + } + } + } + return false; + } + + private boolean jj_3R_249() { + if (jj_3R_262()) return true; + return false; + } + + private boolean jj_3R_220() { + if (jj_scan_token(MM)) return true; + return false; + } + + private boolean jj_3R_193() { + Token xsp; + if (jj_3R_214()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3R_214()) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_219() { + if (jj_scan_token(CM)) return true; + return false; + } + + private boolean jj_3R_192() { + if (jj_3R_213()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_271()) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_218() { + if (jj_scan_token(PT)) return true; + return false; + } + + private boolean jj_3R_178() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_192()) { + jj_scanpos = xsp; + if (jj_3R_193()) return true; + } + return false; + } + + private boolean jj_3R_217() { + if (jj_scan_token(PERCENTAGE)) return true; + return false; + } + + private boolean jj_3R_243() { + if (jj_3R_211()) return true; + if (jj_3R_178()) return true; + return false; + } + + private boolean jj_3R_203() { + if (jj_3R_245()) return true; + return false; + } - private boolean jj_3_8() { - Token xsp; - xsp = jj_scanpos; - if (jj_3_9()) { - jj_scanpos = xsp; - } - if (jj_3R_184()) { - return true; - } - return false; + private boolean jj_3R_216() { + if (jj_scan_token(NUMBER)) return true; + return false; + } + + private boolean jj_3R_215() { + if (jj_3R_253()) return true; + return false; + } + + private boolean jj_3R_195() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_215()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_216()) { + jj_scanpos = xsp; + if (jj_3R_217()) { + jj_scanpos = xsp; + if (jj_3R_218()) { + jj_scanpos = xsp; + if (jj_3R_219()) { + jj_scanpos = xsp; + if (jj_3R_220()) { + jj_scanpos = xsp; + if (jj_3R_221()) { + jj_scanpos = xsp; + if (jj_3R_222()) { + jj_scanpos = xsp; + if (jj_3R_223()) { + jj_scanpos = xsp; + if (jj_3R_224()) { + jj_scanpos = xsp; + if (jj_3R_225()) { + jj_scanpos = xsp; + if (jj_3R_226()) { + jj_scanpos = xsp; + if (jj_3R_227()) { + jj_scanpos = xsp; + if (jj_3R_228()) { + jj_scanpos = xsp; + if (jj_3R_229()) { + jj_scanpos = xsp; + if (jj_3R_230()) { + jj_scanpos = xsp; + if (jj_3R_231()) { + jj_scanpos = xsp; + if (jj_3R_232()) { + jj_scanpos = xsp; + if (jj_3R_233()) { + jj_scanpos = xsp; + if (jj_3R_234()) { + jj_scanpos = xsp; + if (jj_3R_235()) { + jj_scanpos = xsp; + if (jj_3R_236()) return true; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return false; + } + + private boolean jj_3R_181() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_195()) { + jj_scanpos = xsp; + if (jj_3R_196()) return true; + } + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_256() { + if (jj_scan_token(HASH)) return true; + return false; + } + + private boolean jj_3R_245() { + if (jj_3R_186()) return true; + return false; + } + + private boolean jj_3R_257() { + if (jj_scan_token(URL)) return true; + return false; + } + + private boolean jj_3_2() { + if (jj_3R_177()) return true; + if (jj_3R_178()) return true; + return false; + } + + private boolean jj_3R_202() { + if (jj_3R_181()) return true; + return false; + } + + private boolean jj_3R_184() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_202()) { + jj_scanpos = xsp; + if (jj_3R_203()) return true; } + return false; + } - private boolean jj_3R_186() { - if (jj_scan_token(VARIABLE)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } + private boolean jj_3_9() { + if (jj_3R_185()) return true; + return false; + } - private boolean jj_3R_189() { - if (jj_scan_token(SEMICOLON)) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; + private boolean jj_3R_198() { + if (jj_scan_token(COMMA)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } } + if (jj_3R_197()) return true; + return false; + } - private boolean jj_3R_187() { - if (jj_3R_184()) { - return true; - } - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3_8()) { - jj_scanpos = xsp; - break; - } - } - return false; - } + private boolean jj_3R_242() { + if (jj_3R_178()) return true; + return false; + } - private boolean jj_3R_244() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_259()) { - jj_scanpos = xsp; - if (jj_3R_260()) { - return true; - } - } - return false; + private boolean jj_3R_197() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_242()) { + jj_scanpos = xsp; + if (jj_3R_243()) return true; } - - private boolean jj_3R_259() { - if (jj_scan_token(IDENT)) { - return true; - } - return false; + while (true) { + xsp = jj_scanpos; + if (jj_3_2()) { jj_scanpos = xsp; break; } } - - private boolean jj_3R_199() { - Token xsp; - if (jj_3R_244()) { - return true; - } - while (true) { - xsp = jj_scanpos; - if (jj_3R_244()) { - jj_scanpos = xsp; - break; - } - } - while (true) { - xsp = jj_scanpos; - if (jj_scan_token(1)) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - /** Generated Token Manager. */ - public ParserTokenManager token_source; - /** Current token. */ - public Token token; - /** Next token. */ - public Token jj_nt; - private int jj_ntk; - private Token jj_scanpos, jj_lastpos; - private int jj_la; - private int jj_gen; - final private int[] jj_la1 = new int[261]; - static private int[] jj_la1_0; - static private int[] jj_la1_1; - static private int[] jj_la1_2; - static private int[] jj_la1_3; - static { - jj_la1_init_0(); - jj_la1_init_1(); - jj_la1_init_2(); - jj_la1_init_3(); - } - - private static void jj_la1_init_0() { - jj_la1_0 = new int[] { 0x0, 0x302, 0x302, 0x0, 0x300, 0x2, 0x2, 0x2, - 0xd4c40000, 0x0, 0x300, 0x2, 0x300, 0x2, 0x0, 0x2, 0x2, 0x2, - 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x0, 0x2, 0x100000, 0x2, - 0x0, 0x2, 0x2, 0xd4c40000, 0xd4c40000, 0x2, 0x2, 0x2, - 0xd4fd1500, 0xd4fd1500, 0x2, 0x2, 0x2, 0x0, 0x0, 0x2, 0x0, - 0x200000, 0x2, 0x0, 0x2, 0x2, 0x2, 0x2, 0x0, 0x200000, 0x2, - 0x0, 0x2, 0x391500, 0xc40000, 0xc40002, 0xc40000, 0x2, 0x2, - 0x80120002, 0x80120002, 0x2, 0x0, 0x0, 0x2, 0x2, 0x2, 0x2, - 0xd4c40000, 0xd4c40000, 0x2, 0x100000, 0x2, 0xd4c40000, 0x2, - 0x84000000, 0x84000000, 0x84000000, 0x84000000, 0xd4000000, - 0x0, 0x0, 0x0, 0x0, 0x50000000, 0x2, 0x2, 0x3f000, 0x2, 0x0, - 0x2, 0x3f000, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x200000, 0x0, - 0xd4c40000, 0x0, 0x134e0002, 0x2, 0xd4c40000, 0xd4c40000, 0x2, - 0x0, 0x2, 0x134e0002, 0x0, 0x2, 0xd4c40000, 0xd4c40000, 0x2, - 0x134e0002, 0x2, 0x2, 0x2, 0x0, 0x2, 0xd4c40000, 0x2, 0x2, - 0x100000, 0x2, 0x2, 0x2, 0x2, 0x0, 0x2, 0xd4c40000, 0xd4c40000, - 0x2, 0x100000, 0x2, 0x2, 0x2, 0x100000, 0x0, 0x0, 0x800c0000, - 0x2, 0x0, 0x100000, 0x2, 0x800c0000, 0x2, 0x0, 0x2, 0x2, 0x0, - 0x2, 0x200000, 0x2, 0xd4c40000, 0xd4c40000, 0x2, 0x200400, 0x2, - 0x2, 0x0, 0x2, 0x0, 0x2, 0x2, 0x2, 0x100000, 0x2, 0x2, 0x2, - 0x2, 0x2, 0x0, 0x2, 0x2, 0x2, 0x100000, 0x2, 0x2, 0x2, 0x0, - 0x2, 0x2, 0x2, 0x100000, 0x2, 0x2, 0x0, 0x2, 0x0, 0x2, 0x2, - 0x2, 0x100000, 0x0, 0x2, 0x2, 0x0, 0x2, 0x2, 0x2, 0x200000, - 0x2, 0x2, 0x200000, 0x2, 0x2, 0x0, 0x200000, 0x2, 0x0, 0x2, - 0x0, 0xd4c40000, 0x2, 0x0, 0x2, 0x0, 0x200000, 0x2, 0x0, 0x2, - 0x800c0400, 0x2, 0x0, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, - 0x321c0000, 0xc0000, 0x800c0000, 0xc0000, 0x0, 0x80000000, 0x0, - 0x80000000, 0x800c0000, 0x2, 0x2, 0x800c0000, 0x2, 0xd4c40000, - 0x2, 0x2, 0x2, 0x0, 0x200000, 0x2, 0x0, 0x2, }; - } - - private static void jj_la1_init_1() { - jj_la1_1 = new int[] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x566000c0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, - 0x80, 0x0, 0x0, 0x120000, 0x120000, 0x0, 0x120000, 0x0, 0x0, - 0x0, 0x120000, 0x0, 0x0, 0x564000c0, 0x564000c0, 0x0, 0x0, 0x0, - 0x60001c0, 0x60001c0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x80, 0x0, - 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, - 0x100, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc2, 0xc2, 0x0, 0x80, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x564000c0, 0x564000c0, 0x0, 0x0, 0x0, - 0xc0, 0x0, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x50000000, 0x64000c0, 0x50000000, 0x3f, - 0x0, 0x564000c0, 0x564000c0, 0x0, 0x80000000, 0x0, 0x3f, 0x0, - 0x0, 0x564000c0, 0x564000c0, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x564000c0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, - 0x564000c0, 0x564000c0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, - 0x40, 0x160040, 0x0, 0x40, 0x0, 0x0, 0x160040, 0x0, 0x40, 0x0, - 0x0, 0x80, 0x0, 0x0, 0x0, 0x61200c0, 0x61200c0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, - 0x6000000, 0x0, 0x0, 0x60000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x6000000, 0xc0, 0x0, - 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, 0x160000, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x160000, 0x0, - 0x0, 0x0, 0x160000, 0x160000, 0x160000, 0x0, 0x0, 0x160000, - 0x0, 0x60000c0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x80, 0x0, }; - } - - private static void jj_la1_init_2() { - jj_la1_2 = new int[] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x100, - 0x1000, 0x0, 0x0, 0x0, 0x0, 0x880, 0x0, 0x0, 0x0, 0x100, 0x100, - 0x0, 0x0, 0x2008, 0x2008, 0x0, 0x2000, 0x0, 0x0, 0x0, 0x2000, - 0x0, 0x0, 0x1119, 0x1119, 0x0, 0x0, 0x0, 0x2b80, 0x2b80, 0x0, - 0x0, 0x0, 0x100, 0x0, 0x0, 0x100, 0x0, 0x0, 0x100, 0x0, 0x0, - 0x0, 0x0, 0x100, 0x0, 0x0, 0x100, 0x0, 0x2a80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x380, 0x380, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x0, - 0x1119, 0x1119, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x0, 0x0, 0x0, 0x0, - 0x180, 0x0, 0x0, 0x0, 0x0, 0x100, 0x0, 0x40, 0x0, 0x0, 0x0, - 0x109, 0x1000, 0x1300, 0x0, 0x1109, 0x1109, 0x0, 0x0, 0x0, - 0x1300, 0x20, 0x0, 0x1109, 0x1109, 0x0, 0x1300, 0x0, 0x0, 0x0, - 0x1100, 0x0, 0x1109, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x100, - 0x0, 0x1109, 0x1109, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1000, - 0x1000, 0xfffffb80, 0x0, 0x0, 0x0, 0x0, 0xfffffb80, 0x0, 0x0, - 0x0, 0x0, 0x1100, 0x0, 0x0, 0x0, 0x2100, 0x2100, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x100, 0x0, 0x0, 0x100, 0x0, 0x0, 0x100, 0x0, 0x0, 0x0, 0x100, - 0x0, 0x0, 0x100, 0x0, 0xfffffb80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfffffb80, 0x0, 0xffffe200, 0x0, - 0x100, 0x980, 0xffffeb80, 0x0, 0x0, 0xfffffb80, 0x0, 0x100, - 0x0, 0x0, 0x0, 0x100, 0x0, 0x0, 0x100, 0x0, }; - } - - private static void jj_la1_init_3() { - jj_la1_3 = new int[] { 0x8, 0x80, 0x80, 0x2, 0x80, 0x0, 0x0, 0x0, 0x75, - 0x0, 0x80, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc5, - 0xc5, 0x0, 0x0, 0x0, 0xc401bf, 0xc401bf, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xc401be, 0x0, 0x0, 0x0, 0x0, 0x0, 0x400000, - 0x400000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc7, 0xc7, 0x0, - 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x400000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x45, 0x80, 0x200000, 0x0, - 0xe5, 0xe5, 0x0, 0x0, 0x0, 0x200000, 0x0, 0x0, 0xe5, 0xe5, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc5, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x400000, 0x0, 0xf5, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x440001, 0x0, 0x0, 0x0, 0x0, 0x440001, 0x0, - 0x0, 0x0, 0x0, 0x400000, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, - 0x0, 0x0, 0x380000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x100, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x440001, 0x0, 0x100, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x440001, 0x0, 0x400000, - 0x0, 0x0, 0x40001, 0x440001, 0x0, 0x0, 0x440001, 0x0, 0x37, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; - } - - final private JJCalls[] jj_2_rtns = new JJCalls[9]; - private boolean jj_rescan = false; - private int jj_gc = 0; - - /** Constructor with user supplied CharStream. */ - public Parser(CharStream stream) { - token_source = new ParserTokenManager(stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 261; i++) { - jj_la1[i] = -1; - } - for (int i = 0; i < jj_2_rtns.length; i++) { - jj_2_rtns[i] = new JJCalls(); - } - } - - /** Reinitialise. */ - public void ReInit(CharStream stream) { - token_source.ReInit(stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 261; i++) { - jj_la1[i] = -1; - } + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_267() { + if (jj_scan_token(PLUS)) return true; + return false; + } + + private boolean jj_3R_253() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_266()) { + jj_scanpos = xsp; + if (jj_3R_267()) return true; + } + return false; + } + + private boolean jj_3R_266() { + if (jj_scan_token(MINUS)) return true; + return false; + } + + private boolean jj_3R_258() { + if (jj_scan_token(UNICODERANGE)) return true; + return false; + } + + private boolean jj_3_8() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_9()) jj_scanpos = xsp; + if (jj_3R_184()) return true; + return false; + } + + private boolean jj_3_4() { + if (jj_3R_179()) return true; + return false; + } + + private boolean jj_3R_187() { + if (jj_3R_184()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_8()) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_182() { + if (jj_3R_197()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_198()) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3_1() { + if (jj_3R_176()) return true; + return false; + } + + private boolean jj_3R_209() { + if (jj_scan_token(MINUS)) return true; + Token xsp; + if (jj_scan_token(1)) return true; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_208() { + if (jj_scan_token(PLUS)) return true; + Token xsp; + if (jj_scan_token(1)) return true; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3_3() { + if (jj_3R_176()) return true; + return false; + } + + private boolean jj_3R_207() { + if (jj_scan_token(MOD)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_206() { + if (jj_scan_token(ANY)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_260() { + if (jj_scan_token(INTERPOLATION)) return true; + return false; + } + + private boolean jj_3R_205() { + if (jj_scan_token(DIV)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_204() { + if (jj_scan_token(COMMA)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_185() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_204()) { + jj_scanpos = xsp; + if (jj_3R_205()) { + jj_scanpos = xsp; + if (jj_3R_206()) { + jj_scanpos = xsp; + if (jj_3R_207()) { + jj_scanpos = xsp; + if (jj_3R_208()) { + jj_scanpos = xsp; + if (jj_3R_209()) return true; + } + } + } + } + } + return false; + } + + private boolean jj_3R_210() { + if (jj_scan_token(GUARDED_SYM)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_186() { + if (jj_scan_token(VARIABLE)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_189() { + if (jj_scan_token(SEMICOLON)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_244() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_259()) { + jj_scanpos = xsp; + if (jj_3R_260()) return true; + } + return false; + } + + private boolean jj_3R_259() { + if (jj_scan_token(IDENT)) return true; + return false; + } + + private boolean jj_3R_199() { + Token xsp; + if (jj_3R_244()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3R_244()) { jj_scanpos = xsp; break; } + } + while (true) { + xsp = jj_scanpos; + if (jj_scan_token(1)) { jj_scanpos = xsp; break; } + } + return false; + } + + private boolean jj_3R_188() { + if (jj_3R_210()) return true; + return false; + } + + /** Generated Token Manager. */ + public ParserTokenManager token_source; + /** Current token. */ + public Token token; + /** Next token. */ + public Token jj_nt; + private int jj_ntk; + private Token jj_scanpos, jj_lastpos; + private int jj_la; + private int jj_gen; + final private int[] jj_la1 = new int[263]; + static private int[] jj_la1_0; + static private int[] jj_la1_1; + static private int[] jj_la1_2; + static private int[] jj_la1_3; + static { + jj_la1_init_0(); + jj_la1_init_1(); + jj_la1_init_2(); + jj_la1_init_3(); + } + private static void jj_la1_init_0() { + jj_la1_0 = new int[] {0x0,0x302,0x302,0x0,0x300,0x2,0x2,0x2,0xd4c40000,0x0,0x300,0x2,0x300,0x2,0x0,0x2,0x2,0x2,0x0,0x0,0x2,0x2,0x0,0x0,0x2,0x0,0x2,0x100000,0x2,0x0,0x2,0x2,0xd4c40000,0xd4c40000,0x2,0x2,0x2,0xd4fd1500,0x2,0xd4fd1500,0x2,0x2,0x0,0x0,0x2,0x0,0x200000,0x2,0x0,0x2,0x2,0x2,0x2,0x0,0x200000,0x2,0x0,0x2,0x391500,0xc40000,0xc40002,0xc40000,0x2,0x2,0x80120002,0x80120002,0x2,0x0,0x0,0x2,0x2,0x2,0x2,0xd4c40000,0xd4c40000,0x2,0x100000,0x2,0xd4c40000,0x2,0x84000000,0x84000000,0x84000000,0x84000000,0xd4000000,0x0,0x0,0x0,0x0,0x50000000,0x2,0x2,0x3f000,0x2,0x0,0x2,0x3f000,0x0,0x2,0x0,0x2,0x0,0x2,0x200000,0x0,0xd4c40000,0x0,0x134e0002,0x2,0xd4c40000,0xd4c40000,0x2,0x0,0x2,0x134e0002,0x0,0x2,0xd4c40000,0xd4c40000,0x2,0x134e0002,0x2,0x2,0x2,0x0,0x2,0xd4c40000,0x2,0x2,0x100000,0x2,0x2,0x2,0x2,0x0,0x2,0xd4c40000,0xd4c40000,0x2,0x100000,0x2,0x0,0x2,0x2,0x100000,0x0,0x0,0x800c0000,0x2,0x0,0x100000,0x2,0x800c0000,0x2,0x0,0x800c0000,0x2,0x2,0x0,0x200400,0x2,0x200000,0x2,0xd4c40000,0xd4c40000,0x2,0x2,0x2,0x0,0x2,0x0,0x2,0x2,0x2,0x100000,0x2,0x2,0x2,0x2,0x2,0x0,0x2,0x2,0x2,0x100000,0x2,0x2,0x2,0x0,0x2,0x2,0x2,0x100000,0x2,0x2,0x0,0x2,0x0,0x2,0x2,0x2,0x100000,0x0,0x2,0x2,0x0,0x2,0x2,0x2,0x200000,0x2,0x2,0x200000,0x2,0x2,0x0,0x200000,0x2,0x0,0x2,0x0,0xd4c40000,0x2,0x0,0x2,0x0,0x200000,0x2,0x0,0x2,0x800c0400,0x2,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x321c0000,0xc0000,0x800c0000,0xc0000,0x0,0x80000000,0x0,0x80000000,0x800c0000,0x2,0x2,0x800c0000,0x2,0xd4c40000,0x2,0x2,0x2,0x0,0x200000,0x2,0x0,0x2,}; + } + private static void jj_la1_init_1() { + jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x566000c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x80,0x0,0x0,0x120000,0x120000,0x0,0x120000,0x0,0x0,0x0,0x120000,0x0,0x0,0x564000c0,0x564000c0,0x0,0x0,0x0,0x60001c0,0x0,0x60001c0,0x0,0x0,0x0,0x40,0x0,0x80,0x0,0x0,0x80,0x0,0x0,0x0,0x0,0x80,0x0,0x0,0x80,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0xc2,0xc2,0x0,0x80,0x80,0x0,0x0,0x0,0x0,0x564000c0,0x564000c0,0x0,0x0,0x0,0xc0,0x0,0x40,0x40,0x40,0x40,0xc0,0x80,0x80,0x80,0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x50000000,0x64000c0,0x50000000,0x3f,0x0,0x564000c0,0x564000c0,0x0,0x80000000,0x0,0x3f,0x0,0x0,0x564000c0,0x564000c0,0x0,0x3f,0x0,0x0,0x0,0x0,0x0,0x564000c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x564000c0,0x564000c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40,0x40,0x160040,0x0,0x40,0x0,0x0,0x160040,0x0,0x40,0x160000,0x0,0x0,0x80,0x0,0x0,0x0,0x0,0x61200c0,0x61200c0,0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x0,0x6000000,0x0,0x0,0x60000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x0,0x80,0x0,0x6000000,0xc0,0x0,0x0,0x0,0x80,0x0,0x0,0x80,0x0,0x160000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x160000,0x0,0x0,0x0,0x160000,0x160000,0x160000,0x0,0x0,0x160000,0x0,0x60000c0,0x0,0x0,0x0,0x80,0x0,0x0,0x80,0x0,}; + } + private static void jj_la1_init_2() { + jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100,0x1000,0x0,0x0,0x0,0x0,0x880,0x0,0x0,0x0,0x100,0x100,0x0,0x0,0x2008,0x2008,0x0,0x2000,0x0,0x0,0x0,0x2000,0x0,0x0,0x1119,0x1119,0x0,0x0,0x0,0x2b88,0x0,0x2b88,0x0,0x0,0x100,0x0,0x0,0x100,0x0,0x0,0x100,0x0,0x0,0x0,0x0,0x100,0x0,0x0,0x100,0x0,0x2a80,0x0,0x0,0x0,0x0,0x0,0x380,0x380,0x0,0x100,0x100,0x0,0x0,0x0,0x0,0x1119,0x1119,0x0,0x0,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x100,0x100,0x100,0x100,0x100,0x100,0x0,0x0,0x0,0x0,0x180,0x0,0x0,0x0,0x0,0x100,0x0,0x40,0x0,0x0,0x0,0x109,0x1000,0x1300,0x0,0x1109,0x1109,0x0,0x0,0x0,0x1300,0x20,0x0,0x1109,0x1109,0x0,0x1300,0x0,0x0,0x0,0x1100,0x0,0x1109,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100,0x0,0x1109,0x1109,0x0,0x0,0x0,0x1000,0x0,0x0,0x0,0x1000,0x1000,0xfffffb80,0x0,0x0,0x0,0x0,0xfffffb80,0x0,0x0,0xfffffb80,0x0,0x0,0x1100,0x0,0x0,0x0,0x0,0x2100,0x2100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100,0x0,0x0,0x100,0x0,0x0,0x100,0x0,0x0,0x0,0x100,0x0,0x0,0x100,0x0,0xfffffb80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfffffb80,0x0,0xffffe200,0x0,0x100,0x980,0xffffeb80,0x0,0x0,0xfffffb80,0x0,0x100,0x0,0x0,0x0,0x100,0x0,0x0,0x100,0x0,}; + } + private static void jj_la1_init_3() { + jj_la1_3 = new int[] {0x8,0x80,0x80,0x2,0x80,0x0,0x0,0x0,0x75,0x0,0x80,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc5,0xc5,0x0,0x0,0x0,0xc401bf,0x0,0xc401bf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc401be,0x0,0x0,0x0,0x0,0x0,0x400000,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc7,0xc7,0x0,0x0,0x0,0x1,0x0,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400000,0x0,0x0,0x0,0x0,0x0,0x45,0x80,0x200000,0x0,0xe5,0xe5,0x0,0x0,0x0,0x200000,0x0,0x0,0xe5,0xe5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400000,0x0,0xf5,0xf5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x440001,0x0,0x0,0x0,0x0,0x440001,0x0,0x0,0x440001,0x0,0x0,0x400000,0x0,0x0,0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x380000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x440001,0x0,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x440001,0x0,0x400000,0x0,0x0,0x40001,0x440001,0x0,0x0,0x440001,0x0,0x37,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}; + } + final private JJCalls[] jj_2_rtns = new JJCalls[9]; + private boolean jj_rescan = false; + private int jj_gc = 0; + + /** Constructor with user supplied CharStream. */ + public Parser(CharStream stream) { + token_source = new ParserTokenManager(stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 263; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Reinitialise. */ + public void ReInit(CharStream stream) { + token_source.ReInit(stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 263; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Constructor with generated Token Manager. */ + public Parser(ParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 263; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + /** Reinitialise. */ + public void ReInit(ParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 263; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + private Token jj_consume_token(int kind) throws ParseException { + Token oldToken; + if ((oldToken = token).next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + if (token.kind == kind) { + jj_gen++; + if (++jj_gc > 100) { + jj_gc = 0; for (int i = 0; i < jj_2_rtns.length; i++) { - jj_2_rtns[i] = new JJCalls(); - } - } - - /** Constructor with generated Token Manager. */ - public Parser(ParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 261; i++) { - jj_la1[i] = -1; - } - for (int i = 0; i < jj_2_rtns.length; i++) { - jj_2_rtns[i] = new JJCalls(); - } - } - - /** Reinitialise. */ - public void ReInit(ParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 261; i++) { - jj_la1[i] = -1; - } - for (int i = 0; i < jj_2_rtns.length; i++) { - jj_2_rtns[i] = new JJCalls(); - } - } - - private Token jj_consume_token(int kind) throws ParseException { - Token oldToken; - if ((oldToken = token).next != null) { - token = token.next; - } else { - token = token.next = token_source.getNextToken(); - } - jj_ntk = -1; - if (token.kind == kind) { - jj_gen++; - if (++jj_gc > 100) { - jj_gc = 0; - for (int i = 0; i < jj_2_rtns.length; i++) { - JJCalls c = jj_2_rtns[i]; - while (c != null) { - if (c.gen < jj_gen) { - c.first = null; - } - c = c.next; - } - } - } - return token; - } - token = oldToken; - jj_kind = kind; - throw generateParseException(); - } - - static private final class LookaheadSuccess extends java.lang.Error { - } - - final private LookaheadSuccess jj_ls = new LookaheadSuccess(); - - private boolean jj_scan_token(int kind) { - if (jj_scanpos == jj_lastpos) { - jj_la--; - if (jj_scanpos.next == null) { - jj_lastpos = jj_scanpos = jj_scanpos.next = token_source - .getNextToken(); - } else { - jj_lastpos = jj_scanpos = jj_scanpos.next; - } - } else { - jj_scanpos = jj_scanpos.next; - } - if (jj_rescan) { - int i = 0; - Token tok = token; - while (tok != null && tok != jj_scanpos) { - i++; - tok = tok.next; - } - if (tok != null) { - jj_add_error_token(kind, i); - } - } - if (jj_scanpos.kind != kind) { - return true; - } - if (jj_la == 0 && jj_scanpos == jj_lastpos) { - throw jj_ls; - } - return false; - } - - /** Get the next Token. */ - final public Token getNextToken() { - if (token.next != null) { - token = token.next; - } else { - token = token.next = token_source.getNextToken(); - } - jj_ntk = -1; - jj_gen++; - return token; - } - - /** Get the specific Token. */ - final public Token getToken(int index) { - Token t = token; - for (int i = 0; i < index; i++) { - if (t.next != null) { - t = t.next; - } else { - t = t.next = token_source.getNextToken(); - } - } - return t; - } - - private int jj_ntk() { - if ((jj_nt = token.next) == null) { - return (jj_ntk = (token.next = token_source.getNextToken()).kind); - } else { - return (jj_ntk = jj_nt.kind); - } - } - - private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>(); - private int[] jj_expentry; - private int jj_kind = -1; - private int[] jj_lasttokens = new int[100]; - private int jj_endpos; - - private void jj_add_error_token(int kind, int pos) { - if (pos >= 100) { - return; - } - if (pos == jj_endpos + 1) { - jj_lasttokens[jj_endpos++] = kind; - } else if (jj_endpos != 0) { - jj_expentry = new int[jj_endpos]; - for (int i = 0; i < jj_endpos; i++) { - jj_expentry[i] = jj_lasttokens[i]; - } - jj_entries_loop: for (java.util.Iterator<?> it = jj_expentries - .iterator(); it.hasNext();) { - int[] oldentry = (int[]) (it.next()); - if (oldentry.length == jj_expentry.length) { - for (int i = 0; i < jj_expentry.length; i++) { - if (oldentry[i] != jj_expentry[i]) { - continue jj_entries_loop; - } - } - jj_expentries.add(jj_expentry); - break jj_entries_loop; - } - } - if (pos != 0) { - jj_lasttokens[(jj_endpos = pos) - 1] = kind; - } - } - } - - /** Generate ParseException. */ - public ParseException generateParseException() { - jj_expentries.clear(); - boolean[] la1tokens = new boolean[120]; - if (jj_kind >= 0) { - la1tokens[jj_kind] = true; - jj_kind = -1; - } - for (int i = 0; i < 261; i++) { - if (jj_la1[i] == jj_gen) { - for (int j = 0; j < 32; j++) { - if ((jj_la1_0[i] & (1 << j)) != 0) { - la1tokens[j] = true; - } - if ((jj_la1_1[i] & (1 << j)) != 0) { - la1tokens[32 + j] = true; - } - if ((jj_la1_2[i] & (1 << j)) != 0) { - la1tokens[64 + j] = true; - } - if ((jj_la1_3[i] & (1 << j)) != 0) { - la1tokens[96 + j] = true; - } - } - } - } - for (int i = 0; i < 120; i++) { - if (la1tokens[i]) { - jj_expentry = new int[1]; - jj_expentry[0] = i; - jj_expentries.add(jj_expentry); - } - } - jj_endpos = 0; - jj_rescan_token(); - jj_add_error_token(0, 0); - int[][] exptokseq = new int[jj_expentries.size()][]; - for (int i = 0; i < jj_expentries.size(); i++) { - exptokseq[i] = jj_expentries.get(i); - } - return new ParseException(token, exptokseq, tokenImage); - } - - /** Enable tracing. */ - final public void enable_tracing() { - } - - /** Disable tracing. */ - final public void disable_tracing() { - } - - private void jj_rescan_token() { - jj_rescan = true; - for (int i = 0; i < 9; i++) { - try { - JJCalls p = jj_2_rtns[i]; - do { - if (p.gen > jj_gen) { - jj_la = p.arg; - jj_lastpos = jj_scanpos = p.first; - switch (i) { - case 0: - jj_3_1(); - break; - case 1: - jj_3_2(); - break; - case 2: - jj_3_3(); - break; - case 3: - jj_3_4(); - break; - case 4: - jj_3_5(); - break; - case 5: - jj_3_6(); - break; - case 6: - jj_3_7(); - break; - case 7: - jj_3_8(); - break; - case 8: - jj_3_9(); - break; - } - } - p = p.next; - } while (p != null); - } catch (LookaheadSuccess ls) { - } - } - jj_rescan = false; - } - - private void jj_save(int index, int xla) { - JJCalls p = jj_2_rtns[index]; - while (p.gen > jj_gen) { - if (p.next == null) { - p = p.next = new JJCalls(); - break; - } - p = p.next; - } - p.gen = jj_gen + xla - jj_la; - p.first = token; - p.arg = xla; - } - - static final class JJCalls { - int gen; - Token first; - int arg; - JJCalls next; - } + JJCalls c = jj_2_rtns[i]; + while (c != null) { + if (c.gen < jj_gen) c.first = null; + c = c.next; + } + } + } + return token; + } + token = oldToken; + jj_kind = kind; + throw generateParseException(); + } + + static private final class LookaheadSuccess extends java.lang.Error { } + final private LookaheadSuccess jj_ls = new LookaheadSuccess(); + private boolean jj_scan_token(int kind) { + if (jj_scanpos == jj_lastpos) { + jj_la--; + if (jj_scanpos.next == null) { + jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); + } else { + jj_lastpos = jj_scanpos = jj_scanpos.next; + } + } else { + jj_scanpos = jj_scanpos.next; + } + if (jj_rescan) { + int i = 0; Token tok = token; + while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; } + if (tok != null) jj_add_error_token(kind, i); + } + if (jj_scanpos.kind != kind) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; + return false; + } + + +/** Get the next Token. */ + final public Token getNextToken() { + if (token.next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + jj_gen++; + return token; + } + +/** Get the specific Token. */ + final public Token getToken(int index) { + Token t = token; + for (int i = 0; i < index; i++) { + if (t.next != null) t = t.next; + else t = t.next = token_source.getNextToken(); + } + return t; + } + + private int jj_ntk() { + if ((jj_nt=token.next) == null) + return (jj_ntk = (token.next=token_source.getNextToken()).kind); + else + return (jj_ntk = jj_nt.kind); + } + + private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>(); + private int[] jj_expentry; + private int jj_kind = -1; + private int[] jj_lasttokens = new int[100]; + private int jj_endpos; + + private void jj_add_error_token(int kind, int pos) { + if (pos >= 100) return; + if (pos == jj_endpos + 1) { + jj_lasttokens[jj_endpos++] = kind; + } else if (jj_endpos != 0) { + jj_expentry = new int[jj_endpos]; + for (int i = 0; i < jj_endpos; i++) { + jj_expentry[i] = jj_lasttokens[i]; + } + jj_entries_loop: for (java.util.Iterator<?> it = jj_expentries.iterator(); it.hasNext();) { + int[] oldentry = (int[])(it.next()); + if (oldentry.length == jj_expentry.length) { + for (int i = 0; i < jj_expentry.length; i++) { + if (oldentry[i] != jj_expentry[i]) { + continue jj_entries_loop; + } + } + jj_expentries.add(jj_expentry); + break jj_entries_loop; + } + } + if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind; + } + } + + /** Generate ParseException. */ + public ParseException generateParseException() { + jj_expentries.clear(); + boolean[] la1tokens = new boolean[120]; + if (jj_kind >= 0) { + la1tokens[jj_kind] = true; + jj_kind = -1; + } + for (int i = 0; i < 263; i++) { + if (jj_la1[i] == jj_gen) { + for (int j = 0; j < 32; j++) { + if ((jj_la1_0[i] & (1<<j)) != 0) { + la1tokens[j] = true; + } + if ((jj_la1_1[i] & (1<<j)) != 0) { + la1tokens[32+j] = true; + } + if ((jj_la1_2[i] & (1<<j)) != 0) { + la1tokens[64+j] = true; + } + if ((jj_la1_3[i] & (1<<j)) != 0) { + la1tokens[96+j] = true; + } + } + } + } + for (int i = 0; i < 120; i++) { + if (la1tokens[i]) { + jj_expentry = new int[1]; + jj_expentry[0] = i; + jj_expentries.add(jj_expentry); + } + } + jj_endpos = 0; + jj_rescan_token(); + jj_add_error_token(0, 0); + int[][] exptokseq = new int[jj_expentries.size()][]; + for (int i = 0; i < jj_expentries.size(); i++) { + exptokseq[i] = jj_expentries.get(i); + } + return new ParseException(token, exptokseq, tokenImage); + } + + /** Enable tracing. */ + final public void enable_tracing() { + } + + /** Disable tracing. */ + final public void disable_tracing() { + } + + private void jj_rescan_token() { + jj_rescan = true; + for (int i = 0; i < 9; i++) { + try { + JJCalls p = jj_2_rtns[i]; + do { + if (p.gen > jj_gen) { + jj_la = p.arg; jj_lastpos = jj_scanpos = p.first; + switch (i) { + case 0: jj_3_1(); break; + case 1: jj_3_2(); break; + case 2: jj_3_3(); break; + case 3: jj_3_4(); break; + case 4: jj_3_5(); break; + case 5: jj_3_6(); break; + case 6: jj_3_7(); break; + case 7: jj_3_8(); break; + case 8: jj_3_9(); break; + } + } + p = p.next; + } while (p != null); + } catch(LookaheadSuccess ls) { } + } + jj_rescan = false; + } + + private void jj_save(int index, int xla) { + JJCalls p = jj_2_rtns[index]; + while (p.gen > jj_gen) { + if (p.next == null) { p = p.next = new JJCalls(); break; } + p = p.next; + } + p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla; + } + + static final class JJCalls { + int gen; + Token first; + int arg; + JJCalls next; + } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj index 5fb7f2315f..f8b6a86af7 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj @@ -40,6 +40,8 @@ import java.util.ArrayList; import java.util.Locale; import java.util.Map; import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; import org.w3c.css.sac.ConditionFactory; import org.w3c.css.sac.Condition; @@ -912,18 +914,24 @@ void media() : <MEDIA_SYM> ( <S> )* mediaStatement(ml) { start = true; documentHandler.startMedia(ml); } - <LBRACE> ( <S> )* ( debuggingDirective() | styleRule() | skipUnknownRule() )* <RBRACE> ( <S> )* + <LBRACE> ( <S> )* ( mediaDirective() )* <RBRACE> ( <S> )* } catch (ParseException e) { reportError(getLocator(), e); skipStatement(); // reportWarningSkipText(getLocator(), skipStatement()); } finally { if (start) { - documentHandler.endMedia(ml); + documentHandler.endMedia(ml); } } } +void mediaDirective() : +{} +{ + debuggingDirective() | styleRule() | skipUnknownRule() | contentDirective() +} + void mediaStatement(MediaListImpl ml) : { Token t; @@ -1485,6 +1493,7 @@ void variable() : ":" ( <S> )* exp=expr() ( guarded=guarded() )?(";"(<S>)*)+ //raw=skipStatementUntilSemiColon() { + exp = replaceNullValues(exp); documentHandler.variable(name, exp, guarded); } }catch (JumpException e) { @@ -1514,6 +1523,24 @@ void variable() : } } +JAVACODE +LexicalUnitImpl replaceNullValues(LexicalUnitImpl unit) { + if(unit == null){ + return null; + } + if (unit.getNextLexicalUnit() != null) { + unit.setNextLexicalUnit(replaceNullValues(unit.getNextLexicalUnit())); + } + if (unit.getLexicalUnitType() == SCSSLexicalUnit.SAC_IDENT + && "null".equals(unit.getStringValue())) { + LexicalUnitImpl next = unit.getNextLexicalUnit(); + unit = LexicalUnitImpl.createNull(unit.getLineNumber(), unit.getColumnNumber(), + unit.getPreviousLexicalUnit()); + unit.setNextLexicalUnit(next); + } + return unit; +} + void controlDirective() : {} { @@ -1655,21 +1682,30 @@ ArrayList<VariableNode> arglist() : boolean hasNonOptionalArgument = false; } { - arg=mixinArg() ( <COMMA> (<S>)* { hasNonOptionalArgument = checkMixinForNonOptionalArguments(arg, hasNonOptionalArgument); args.add(arg); } - arg=mixinArg() )* - { hasNonOptionalArgument = checkMixinForNonOptionalArguments(arg, hasNonOptionalArgument); args.add(arg); + (arg=mixinArg() ( <COMMA> (<S>)* { hasNonOptionalArgument = checkMixinForNonOptionalArguments(arg, hasNonOptionalArgument); args.add(arg); } + arg=mixinArg() )* + { hasNonOptionalArgument = checkMixinForNonOptionalArguments(arg, hasNonOptionalArgument); args.add(arg); } + )? + { return args; } } JAVACODE -boolean checkMixinForNonOptionalArguments(VariableNode arg, boolean hasNonOptionalArguments)
{ +boolean checkMixinForNonOptionalArguments(VariableNode arg, boolean hasNonOptionalArguments) +{ boolean currentArgHasArguments = arg.getExpr() != null && arg.getExpr().getLexicalUnitType() == LexicalUnitImpl.SCSS_VARIABLE && arg.getExpr().getNextLexicalUnit() != null; -
if(currentArgHasArguments)
{ - if(hasNonOptionalArguments)
{
throw new ParseException("Sass Error: Required argument $"+ arg.getName() +" must come before any optional arguments."); + + if(currentArgHasArguments) + { + if(hasNonOptionalArguments) + { + throw new ParseException("Sass Error: Required argument $"+ arg.getName() +" must come before any optional arguments."); } return hasNonOptionalArguments; - }else
{
return true; + }else + { + return true; } } @@ -1684,9 +1720,13 @@ VariableNode mixinArg() : { name=variableName() (< COLON > (< S >)* - (
first = nonVariableTerm(null)
{ - prev = first;
} - (LOOKAHEAD(3)(< COMMA >(< S >)*)? prev = nonVariableTerm(prev))*
) + ( + first = nonVariableTerm(null) + { + prev = first; + } + (LOOKAHEAD(3)(< COMMA >(< S >)*)? prev = nonVariableTerm(prev))* + ) | (variable = < VARIABLE >{ first = LexicalUnitImpl.createVariable(token.beginLine, token.beginColumn, prev, variable.image);} @@ -1706,10 +1746,11 @@ ArrayList<LexicalUnitImpl> argValuelist() : LexicalUnitImpl prev = null; } { - first = term(null) { args.add(first); prev = first;}((< COLON > (< S >)*)?next=term(prev){prev.setNextLexicalUnit(next); prev = next;})* - ( <COMMA> (<S>)* - first = term(null) { args.add(first); prev = first;}((< COLON > (< S >)*)?next=term(prev){prev.setNextLexicalUnit(next); prev = next;})* - )* + (first = term(null) { args.add(first); prev = first;}((< COLON > (< S >)*)?next=term(prev){prev.setNextLexicalUnit(next); prev = next;})* + ( <COMMA> (<S>)* + first = term(null) { args.add(first); prev = first;}((< COLON > (< S >)*)?next=term(prev){prev.setNextLexicalUnit(next); prev = next;})* + )* + )? {return args;} } @@ -1721,17 +1762,33 @@ void includeDirective() : { <INCLUDE_SYM> (<S>)* - (name = property()|name = variableName(){ name = "$"+name;} - |(name = functionName() - args = argValuelist()) <RPARAN>(<S>)*) - ((";"(<S>)*)+ - {documentHandler.includeDirective(name, args);} - | <LBRACE> (<S>)* {documentHandler.startIncludeContentBlock(name, args);} - (styleRuleOrDeclarationOrNestedProperties() | keyframeSelector())* - <RBRACE> (<S>)* {documentHandler.endIncludeContentBlock();} - ) + (name = property() | name = variableName(){ name = "$"+name;} + | (name = functionName() args = argValuelist()) <RPARAN>(<S>)*) + {documentHandler.startInclude(name, args);} + (includeDirectiveBlockContents() | includeDirectiveTerminator()) + {documentHandler.endInclude();} +} + +void includeDirectiveTerminator(): +{} +{ + try { + (";"(<S>)*)+ + } + catch (ParseException e) { + acceptMissingSemicolonBeforeRbrace(e); + } +} + +void includeDirectiveBlockContents(): +{} +{ + <LBRACE> (<S>)* + (styleRuleOrDeclarationOrNestedProperties() | keyframeSelector())* + <RBRACE> (<S>)* } + String interpolation() : { Token n; @@ -1873,39 +1930,66 @@ String listModifyDirectiveArgs(int nest) { t = getToken(1); String s = t.image; - if(t.kind == VARIABLE||t.kind == IDENT)
{ + if(t.kind == VARIABLE||t.kind == IDENT) + { list += s; - }else if(s.toLowerCase().equals("auto")||s.toLowerCase().equals("space")||s.toLowerCase().equals("comma"))
{ + }else if(s.toLowerCase().equals("auto")||s.toLowerCase().equals("space")||s.toLowerCase().equals("comma")) + { int i = 2; Token temp = getToken(i); boolean isLast = true; while(temp.kind != SEMICOLON) - {
if(temp.kind != RPARAN || temp.kind != S) - {
isLast = false;
} + { + if(temp.kind != RPARAN || temp.kind != S) + { + isLast = false; + } i++; temp = getToken(i); } - if(isLast)
{
return list; + if(isLast) + { + return list; } - }
else if(t.kind == STRING)
{
list += s.substring(1,s.length()).substring(0,s.length()-2); + } + else if(t.kind == STRING) + { + list += s.substring(1,s.length()).substring(0,s.length()-2); - }else if(t.kind == LPARAN)
{
nesting++; - if(nesting > nest+1)
{
throw new CSSParseException("Only one ( ) pair per parameter allowed", getLocator()); + }else if(t.kind == LPARAN) + { + nesting++; + if(nesting > nest+1) + { + throw new CSSParseException("Only one ( ) pair per parameter allowed", getLocator()); } - }else if(t.kind == RPARAN)
{
nesting--; - if(nesting == 0)
{ + }else if(t.kind == RPARAN) + { + nesting--; + if(nesting == 0) + { return list; } - } else if(t.kind == COMMA)
{ - if(nesting == nest)
{ - return list;
}else
{ - list += ",";
} + } else if(t.kind == COMMA) + { + if(nesting == nest) + { + return list; + }else + { + list += ","; + } - }else if(t.kind == S)
{ - list += " ";
} else if(t.kind == LBRACE)
{ - throw new CSSParseException("Invalid token,'{' found", getLocator());
} -
getNextToken(); + }else if(t.kind == S) + { + list += " "; + } else if(t.kind == LBRACE) + { + throw new CSSParseException("Invalid token,'{' found", getLocator()); + } + + getNextToken(); } } @@ -1929,11 +2013,16 @@ void debugDirective() : { <DEBUG_SYM> { - String content = skipStatementUntilSemiColon(); + String content = skipStatementUntil(new int[] {SEMICOLON,RBRACE,EOF}); // TODO should evaluate the content expression, call documentHandler.debugDirective() etc. - System.out.println(content); + Logger.getLogger(Parser.class.getName()).log(Level.INFO, content); + } + try { + ";" (<S>)* + } + catch (ParseException e) { + acceptMissingSemicolonBeforeRbrace(e); } - (<S>)* } void warnDirective() : @@ -1941,11 +2030,16 @@ void warnDirective() : { <WARN_SYM> { - String content = skipStatementUntilSemiColon(); + String content = skipStatementUntil(new int[] {SEMICOLON,RBRACE,EOF}); // TODO should evaluate the content expression, call documentHandler.warnDirective() etc. - System.err.println(content); + Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, content); + } + try { + ";" (<S>)* + } + catch (ParseException e) { + acceptMissingSemicolonBeforeRbrace(e); } - (<S>)* } Node forDirective() : @@ -1988,8 +2082,13 @@ void extendDirective() : <EXTEND_SYM> (<S>)* list = selectorList() - (";"(<S>)*)+ {documentHandler.extendDirective(list);} + try { + (";"(<S>)*)+ + } + catch (ParseException e) { + acceptMissingSemicolonBeforeRbrace(e); + } } void contentDirective() : @@ -1997,7 +2096,12 @@ void contentDirective() : { <CONTENT_SYM> (<S>)* - (";"(<S>)*)+ + try { + (";"(<S>)*)+ + } + catch (ParseException e) { + acceptMissingSemicolonBeforeRbrace(e); + } {documentHandler.contentDirective();} } @@ -2297,14 +2401,20 @@ LexicalUnitImpl term(LexicalUnitImpl prev) : } } -LexicalUnitImpl variableTerm(LexicalUnitImpl prev) :
{ +LexicalUnitImpl variableTerm(LexicalUnitImpl prev) : +{ LexicalUnitImpl result = null; - String varName = "";
}
{ + String varName = ""; +} +{ varName = variableName() {result = LexicalUnitImpl.createVariable(token.beginLine, token.beginColumn, - prev, varName); return result;}
} + prev, varName); return result;} +} -LexicalUnitImpl nonVariableTerm(LexicalUnitImpl prev) :
{
LexicalUnitImpl result = null; +LexicalUnitImpl nonVariableTerm(LexicalUnitImpl prev) : +{ +LexicalUnitImpl result = null; Token n = null; char op = ' '; String varName; @@ -2427,7 +2537,9 @@ LexicalUnitImpl nonVariableTerm(LexicalUnitImpl prev) :
{
LexicalUnitImpl result | result=unicode(prev) ) ) ( <S> )* { - return result;
}
} + return result; + } +} /** * Handle all CSS2 functions. @@ -2766,27 +2878,27 @@ String skipStatementUntilMatchingRightParan(){ JAVACODE String skipStatementUntil(int[] symbols){ StringBuffer s = new StringBuffer(); - boolean stop = false; + boolean found = false; Token tok; - while(!stop){ + while(!found){ tok = getToken(1); - if(tok.kind == EOF) { - return null; - } for(int sym : symbols){ if(tok.kind == sym){ - stop = true; + found = true; break; } } - if(!stop){ + if(tok.kind == EOF) { + break; + } + if(!found){ if (tok.image != null) { s.append(tok.image); } getNextToken(); } } - return s.toString().trim(); + return found ? s.toString().trim() : null; } @@ -3021,6 +3133,15 @@ ArrayList<String> _parseSelectors() : } } +JAVACODE +void acceptMissingSemicolonBeforeRbrace( ParseException parseException ) { + Token next = getToken(1); + if (next.kind != RBRACE && next.kind!=EOF) { + throw parseException; + } +} + + /* * Local Variables: * compile-command: javacc Parser.jj & javac Parser.java diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/ParserTokenManager.java b/theme-compiler/src/com/vaadin/sass/internal/parser/ParserTokenManager.java index d54ab4fa7e..0db4e4e2f8 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/parser/ParserTokenManager.java +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/ParserTokenManager.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.Locale; import java.util.Map; import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; import org.w3c.css.sac.ConditionFactory; import org.w3c.css.sac.Condition; import org.w3c.css.sac.SelectorFactory; diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/SCSSLexicalUnit.java b/theme-compiler/src/com/vaadin/sass/internal/parser/SCSSLexicalUnit.java index 709d1d3576..84b0563493 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/parser/SCSSLexicalUnit.java +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/SCSSLexicalUnit.java @@ -22,6 +22,8 @@ public interface SCSSLexicalUnit extends LexicalUnit { static final short SCSS_OPERATOR_LEFT_PAREN = 101; static final short SCSS_OPERATOR_RIGHT_PAREN = 102; + static final short SCSS_NULL = 110; + static final short SAC_LEM = 200; static final short SAC_REM = 201; diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/function/AbsFunctionGenerator.java b/theme-compiler/src/com/vaadin/sass/internal/parser/function/AbsFunctionGenerator.java new file mode 100644 index 0000000000..7f88649e84 --- /dev/null +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/function/AbsFunctionGenerator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.sass.internal.parser.function; + +import com.vaadin.sass.internal.parser.LexicalUnitImpl; + +/** + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class AbsFunctionGenerator implements SCSSFunctionGenerator { + + @Override + public String getFunctionName() { + return "abs"; + } + + @Override + public String printState(LexicalUnitImpl function) { + LexicalUnitImpl firstParam = function.getParameters(); + firstParam.setFloatValue(Math.abs(firstParam.getFloatValue())); + return firstParam.toString(); + } + +} diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/function/CeilFunctionGenerator.java b/theme-compiler/src/com/vaadin/sass/internal/parser/function/CeilFunctionGenerator.java new file mode 100644 index 0000000000..7d19734fe7 --- /dev/null +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/function/CeilFunctionGenerator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.sass.internal.parser.function; + +import com.vaadin.sass.internal.parser.LexicalUnitImpl; + +/** + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class CeilFunctionGenerator implements SCSSFunctionGenerator { + + @Override + public String getFunctionName() { + return "ceil"; + } + + @Override + public String printState(LexicalUnitImpl function) { + LexicalUnitImpl firstParam = function.getParameters(); + firstParam.setFloatValue((float) Math.ceil(firstParam.getFloatValue())); + return firstParam.toString(); + } + +} diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/function/DarkenFunctionGenerator.java b/theme-compiler/src/com/vaadin/sass/internal/parser/function/DarkenFunctionGenerator.java new file mode 100644 index 0000000000..2fbf0b2427 --- /dev/null +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/function/DarkenFunctionGenerator.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.sass.internal.parser.function; + +import com.vaadin.sass.internal.parser.LexicalUnitImpl; +import com.vaadin.sass.internal.util.ColorUtil; + +/** + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class DarkenFunctionGenerator implements SCSSFunctionGenerator { + + @Override + public String getFunctionName() { + return "darken"; + } + + @Override + public String printState(LexicalUnitImpl function) { + LexicalUnitImpl dark = ColorUtil.darken(function); + return dark.toString(); + } +} diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/function/DefaultFunctionGenerator.java b/theme-compiler/src/com/vaadin/sass/internal/parser/function/DefaultFunctionGenerator.java new file mode 100644 index 0000000000..d972a5bee8 --- /dev/null +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/function/DefaultFunctionGenerator.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.sass.internal.parser.function; + +import com.vaadin.sass.internal.parser.LexicalUnitImpl; + +/** + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class DefaultFunctionGenerator implements SCSSFunctionGenerator { + + @Override + public String getFunctionName() { + return null; + } + + @Override + public String printState(LexicalUnitImpl function) { + StringBuilder builder = new StringBuilder(function.getFunctionName()); + return builder.append('(').append(printParameters(function)) + .append(')').toString(); + } + + private String printParameters(LexicalUnitImpl function) { + if (function.getParameters() == null) { + return null; + } + return function.getParameters().toString(); + } +} diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/function/FloorFunctionGenerator.java b/theme-compiler/src/com/vaadin/sass/internal/parser/function/FloorFunctionGenerator.java new file mode 100644 index 0000000000..57a0dcbf56 --- /dev/null +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/function/FloorFunctionGenerator.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.sass.internal.parser.function; + +import com.vaadin.sass.internal.parser.LexicalUnitImpl; + +/** + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class FloorFunctionGenerator implements SCSSFunctionGenerator { + + @Override + public String getFunctionName() { + return "floor"; + } + + @Override + public String printState(LexicalUnitImpl function) { + LexicalUnitImpl firstParam = function.getParameters(); + firstParam + .setFloatValue((float) Math.floor(firstParam.getFloatValue())); + return firstParam.toString(); + } + +} diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/function/LightenFunctionGenerator.java b/theme-compiler/src/com/vaadin/sass/internal/parser/function/LightenFunctionGenerator.java new file mode 100644 index 0000000000..b911593457 --- /dev/null +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/function/LightenFunctionGenerator.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.sass.internal.parser.function; + +import com.vaadin.sass.internal.parser.LexicalUnitImpl; +import com.vaadin.sass.internal.util.ColorUtil; + +/** + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class LightenFunctionGenerator implements SCSSFunctionGenerator { + + @Override + public String getFunctionName() { + return "lighten"; + } + + @Override + public String printState(LexicalUnitImpl function) { + return ColorUtil.lighten(function).toString(); + } + +} diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/function/RoundFunctionGenerator.java b/theme-compiler/src/com/vaadin/sass/internal/parser/function/RoundFunctionGenerator.java new file mode 100644 index 0000000000..b8e8194f21 --- /dev/null +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/function/RoundFunctionGenerator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.sass.internal.parser.function; + +import com.vaadin.sass.internal.parser.LexicalUnitImpl; + +/** + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class RoundFunctionGenerator implements SCSSFunctionGenerator { + + @Override + public String getFunctionName() { + return "round"; + } + + @Override + public String printState(LexicalUnitImpl function) { + LexicalUnitImpl firstParam = function.getParameters(); + firstParam.setFloatValue(Math.round(firstParam.getFloatValue())); + return firstParam.toString(); + } + +} diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/function/SCSSFunctionGenerator.java b/theme-compiler/src/com/vaadin/sass/internal/parser/function/SCSSFunctionGenerator.java new file mode 100644 index 0000000000..4d34b59578 --- /dev/null +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/function/SCSSFunctionGenerator.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.sass.internal.parser.function; + +import com.vaadin.sass.internal.parser.LexicalUnitImpl; + +/** + * Generator class is used to handle SCSS functions. Generator is applied to the + * function lexical unit if its method {@link #getFunctionName()} returns name + * of the function. + * + * If there are no dedicated generator for the function then default generator + * is used. + * + * @since 7.2 + * @author Vaadin Ltd + */ +public interface SCSSFunctionGenerator { + + /** + * Returns function name handled by this generator. Default generator + * returns <code>null</code> and is used if there is no dedicated generator + * for given function. + * + * @since 7.2 + * @return + */ + String getFunctionName(); + + /** + * Prints out the current state of the function. State is SCSS content of + * the function before compilation and compiled CSS content after + * compilation. + * + * @since 7.2 + * @param function + * Function lexical unit to print its state + * @return String state representation of the function + */ + String printState(LexicalUnitImpl function); +} diff --git a/theme-compiler/src/com/vaadin/sass/internal/selector/SelectorUtil.java b/theme-compiler/src/com/vaadin/sass/internal/selector/SelectorUtil.java index 744b560116..c1f26f968e 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/selector/SelectorUtil.java +++ b/theme-compiler/src/com/vaadin/sass/internal/selector/SelectorUtil.java @@ -16,6 +16,9 @@ package com.vaadin.sass.internal.selector; +import java.util.logging.Level; +import java.util.logging.Logger; + import org.w3c.css.sac.CombinatorCondition; import org.w3c.css.sac.Condition; import org.w3c.css.sac.ConditionFactory; @@ -115,7 +118,7 @@ public class SelectorUtil { } else if (selector.getSelectorType() == CompositeSelector.SCSS_COMPOSITE_SELECTOR) { return toString((CompositeSelector) selector); } else { - System.out.println("SU !Unknown selector type, type: " + log("SU !Unknown selector type, type: " + selector.getSelectorType() + ", " + selector.toString()); } return ""; @@ -162,8 +165,8 @@ public class SelectorUtil { PseudoClassConditionImpl pseudoClassCondition = (PseudoClassConditionImpl) condition; return ":" + pseudoClassCondition.getValue(); } else { - System.out.println("CU !condition type not identified, type: " - + conditionType + ", " + condition.toString()); + log("CU !condition type not identified, type: " + conditionType + + ", " + condition.toString()); return ""; } } @@ -330,4 +333,8 @@ public class SelectorUtil { throw new Exception("Invalid selector type"); } } + + private static void log(String msg) { + Logger.getLogger(SelectorUtil.class.getName()).log(Level.INFO, msg); + } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/tree/BlockNode.java b/theme-compiler/src/com/vaadin/sass/internal/tree/BlockNode.java index 6ce67a3abd..8db522ea1a 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/tree/BlockNode.java +++ b/theme-compiler/src/com/vaadin/sass/internal/tree/BlockNode.java @@ -17,6 +17,8 @@ package com.vaadin.sass.internal.tree; import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; import com.vaadin.sass.internal.ScssStylesheet; import com.vaadin.sass.internal.visitor.BlockNodeHandler; @@ -109,7 +111,8 @@ public class BlockNode extends Node implements IVariableNode { BlockNodeHandler.traverse(this); replaceVariables(ScssStylesheet.getVariables()); } catch (Exception e) { - e.printStackTrace(); + Logger.getLogger(BlockNode.class.getName()).log(Level.SEVERE, null, + e); } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/tree/ExtendNode.java b/theme-compiler/src/com/vaadin/sass/internal/tree/ExtendNode.java index 417849d13b..dcabd2ff01 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/tree/ExtendNode.java +++ b/theme-compiler/src/com/vaadin/sass/internal/tree/ExtendNode.java @@ -17,6 +17,8 @@ package com.vaadin.sass.internal.tree; import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; import com.vaadin.sass.internal.visitor.ExtendNodeHandler; @@ -54,7 +56,8 @@ public class ExtendNode extends Node implements IVariableNode { ExtendNodeHandler.traverse(this); getParentNode().removeChild(this); } catch (Exception e) { - e.printStackTrace(); + Logger.getLogger(ExtendNode.class.getName()).log(Level.SEVERE, + null, e); } } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/tree/MixinNode.java b/theme-compiler/src/com/vaadin/sass/internal/tree/MixinNode.java index e702bc8577..c5ffb6d73d 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/tree/MixinNode.java +++ b/theme-compiler/src/com/vaadin/sass/internal/tree/MixinNode.java @@ -19,6 +19,8 @@ package com.vaadin.sass.internal.tree; import java.util.ArrayList; import java.util.Collection; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import com.vaadin.sass.internal.ScssStylesheet; import com.vaadin.sass.internal.parser.LexicalUnitImpl; @@ -119,7 +121,8 @@ public class MixinNode extends Node implements IVariableNode { ScssStylesheet.closeVariableScope(variableScope); } catch (Exception e) { - e.printStackTrace(); + Logger.getLogger(MixinNode.class.getName()).log(Level.SEVERE, null, + e); } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/tree/RuleNode.java b/theme-compiler/src/com/vaadin/sass/internal/tree/RuleNode.java index cc6dbb7b75..a8fa87eb0a 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/tree/RuleNode.java +++ b/theme-compiler/src/com/vaadin/sass/internal/tree/RuleNode.java @@ -58,13 +58,18 @@ public class RuleNode extends Node implements IVariableNode { @Override public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(variable).append(": ").append(value.toString()); - builder.append(important ? " !important;" : ";"); + String stringValue = value.toString() + + (important ? " !important" : ""); + if (!"".equals(stringValue.trim())) { + stringValue = variable + ": " + stringValue + ";"; + } else { + stringValue = ""; + } + if (comment != null) { - builder.append(comment); + stringValue += comment; } - return builder.toString(); + return stringValue; } public boolean isImportant() { diff --git a/theme-compiler/src/com/vaadin/sass/internal/tree/controldirective/IfElseDefNode.java b/theme-compiler/src/com/vaadin/sass/internal/tree/controldirective/IfElseDefNode.java index 735d83a898..8449a9d891 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/tree/controldirective/IfElseDefNode.java +++ b/theme-compiler/src/com/vaadin/sass/internal/tree/controldirective/IfElseDefNode.java @@ -15,6 +15,9 @@ */ package com.vaadin.sass.internal.tree.controldirective; +import java.util.logging.Level; +import java.util.logging.Logger; + import com.vaadin.sass.internal.tree.Node; import com.vaadin.sass.internal.visitor.IfElseNodeHandler; @@ -40,7 +43,8 @@ public class IfElseDefNode extends Node { IfElseNodeHandler.traverse(this); } catch (Exception e) { - e.printStackTrace(); + Logger.getLogger(IfElseDefNode.class.getName()).log(Level.SEVERE, + null, e); } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/util/DeepCopy.java b/theme-compiler/src/com/vaadin/sass/internal/util/DeepCopy.java index bc30ffdd6c..af66eb9a74 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/util/DeepCopy.java +++ b/theme-compiler/src/com/vaadin/sass/internal/util/DeepCopy.java @@ -22,13 +22,15 @@ import java.io.ObjectOutputStream; import java.util.Collection; import java.util.LinkedList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Utility for making deep copies (vs. clone()'s shallow copies) of objects. * Objects are first serialized and then deserialized. Error checking is fairly * minimal in this implementation. If an object is encountered that cannot be * serialized (or that references an object that cannot be serialized) an error - * is printed to System.err and null is returned. Depending on your specific + * is printed to the logger and null is returned. Depending on your specific * application, it might make more sense to have copy(...) re-throw the * exception. */ @@ -56,9 +58,9 @@ public class DeepCopy { obj = in.readObject(); in.close(); } catch (IOException e) { - e.printStackTrace(); + log(e); } catch (ClassNotFoundException cnfe) { - cnfe.printStackTrace(); + log(cnfe); } return obj; } else { @@ -80,4 +82,8 @@ public class DeepCopy { } return copies; } + + private static void log(Throwable e) { + Logger.getLogger(DeepCopy.class.getName()).log(Level.SEVERE, null, e); + } }
\ No newline at end of file diff --git a/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java b/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java index e52767bb5a..daf01a3eab 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java +++ b/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java @@ -19,6 +19,8 @@ package com.vaadin.sass.internal.visitor; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; import org.w3c.css.sac.CSSException; import org.w3c.css.sac.LexicalUnit; @@ -78,9 +80,11 @@ public class ImportNodeHandler { importNode); node.removeChild(importNode); } catch (CSSException e) { - e.printStackTrace(); + Logger.getLogger(ImportNodeHandler.class.getName()) + .log(Level.SEVERE, null, e); } catch (IOException e) { - e.printStackTrace(); + Logger.getLogger(ImportNodeHandler.class.getName()) + .log(Level.SEVERE, null, e); } } else { if (styleSheet != node) { diff --git a/theme-compiler/src/com/vaadin/sass/internal/visitor/VariableNodeHandler.java b/theme-compiler/src/com/vaadin/sass/internal/visitor/VariableNodeHandler.java index 6da035426e..a794def8cb 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/visitor/VariableNodeHandler.java +++ b/theme-compiler/src/com/vaadin/sass/internal/visitor/VariableNodeHandler.java @@ -17,16 +17,20 @@ package com.vaadin.sass.internal.visitor; import com.vaadin.sass.internal.ScssStylesheet; +import com.vaadin.sass.internal.parser.SCSSLexicalUnit; import com.vaadin.sass.internal.tree.VariableNode; public class VariableNodeHandler { public static void traverse(VariableNode node) { - if (ScssStylesheet.getVariable(node.getName()) == null - || !node.isGuarded()) { + VariableNode variable = ScssStylesheet.getVariable(node.getName()); + if (!node.isGuarded() + || variable == null + || variable.getExpr() == null + || (variable.getExpr().getLexicalUnitType() == SCSSLexicalUnit.SCSS_NULL && variable + .getExpr().getNextLexicalUnit() == null)) { ScssStylesheet.addVariable(node); } node.getParentNode().removeChild(node); } - } diff --git a/theme-compiler/src/logging.properties b/theme-compiler/src/logging.properties new file mode 100644 index 0000000000..b563d4b68e --- /dev/null +++ b/theme-compiler/src/logging.properties @@ -0,0 +1,2 @@ +handlers = com.vaadin.sass.CustomConsoleHandler +.level = ALL
\ No newline at end of file diff --git a/theme-compiler/tests/resources/automatic/css/media.css b/theme-compiler/tests/resources/automatic/css/media.css index f4183d9a07..5f7267fa9a 100644 --- a/theme-compiler/tests/resources/automatic/css/media.css +++ b/theme-compiler/tests/resources/automatic/css/media.css @@ -1,3 +1,14 @@ +@media screen { + .v-view { + overflow: visible; + } + .details { + font-size: 1pt; + font-weight: bold; + } + width: 100%; +} + @media screen and (max-width: 480px) { .abc { background: red; diff --git a/theme-compiler/tests/resources/automatic/css/variable-defaults-with-null.css b/theme-compiler/tests/resources/automatic/css/variable-defaults-with-null.css new file mode 100644 index 0000000000..0e3483817b --- /dev/null +++ b/theme-compiler/tests/resources/automatic/css/variable-defaults-with-null.css @@ -0,0 +1,5 @@ +.test { + first: "Non-null"; + second: "Also non-null"; + third: "Not null"; +}
\ No newline at end of file diff --git a/theme-compiler/tests/resources/automatic/scss/media.scss b/theme-compiler/tests/resources/automatic/scss/media.scss index 7db52de9ed..311c5088c8 100644 --- a/theme-compiler/tests/resources/automatic/scss/media.scss +++ b/theme-compiler/tests/resources/automatic/scss/media.scss @@ -1,3 +1,24 @@ +@mixin media-settings { + @media screen { + .v-view { + overflow: visible; + } + @content; + } +} + +@include media-settings { + .details { + font: { + size : 1pt; + weight: bold; + } + } + + width:100%; +} + + @media screen and (max-width: 480px) { .abc { background: red; diff --git a/theme-compiler/tests/resources/automatic/scss/variable-defaults-with-null.scss b/theme-compiler/tests/resources/automatic/scss/variable-defaults-with-null.scss new file mode 100644 index 0000000000..0bfa374304 --- /dev/null +++ b/theme-compiler/tests/resources/automatic/scss/variable-defaults-with-null.scss @@ -0,0 +1,19 @@ +$var: null; +$var: "Non-null" !default; + +$var2: null; +$var2: "Also non-null" !default; +$var2: "Null content" !default; + +$list-of-nulls: null null; +$list-of-nulls: "Non-null" !default; + +$mixed-list: null "Not null" null; +$mixed-list: "null" !default; + +.test { + first: $var; + second: $var2; + hidden: $list-of-nulls; + third: $mixed-list; +}
\ No newline at end of file diff --git a/theme-compiler/tests/resources/sasslangbroken/css/106-test_pseudoclass_remains_at_end_of_selector.css b/theme-compiler/tests/resources/sasslang/css/106-test_pseudoclass_remains_at_end_of_selector.css index 2118fad2a2..2118fad2a2 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/106-test_pseudoclass_remains_at_end_of_selector.css +++ b/theme-compiler/tests/resources/sasslang/css/106-test_pseudoclass_remains_at_end_of_selector.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/107-test_pseudoelement_goes_lefter_than_not.css b/theme-compiler/tests/resources/sasslang/css/107-test_pseudoelement_goes_lefter_than_not.css index 7a53dec628..7a53dec628 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/107-test_pseudoelement_goes_lefter_than_not.css +++ b/theme-compiler/tests/resources/sasslang/css/107-test_pseudoelement_goes_lefter_than_not.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/108-test_pseudoelement_goes_lefter_than_pseudoclass.css b/theme-compiler/tests/resources/sasslang/css/108-test_pseudoelement_goes_lefter_than_pseudoclass.css index a5ae5ac363..a5ae5ac363 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/108-test_pseudoelement_goes_lefter_than_pseudoclass.css +++ b/theme-compiler/tests/resources/sasslang/css/108-test_pseudoelement_goes_lefter_than_pseudoclass.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/109-test_pseudoelement_remains_at_end_of_selector.css b/theme-compiler/tests/resources/sasslang/css/109-test_pseudoelement_remains_at_end_of_selector.css index aa379e70b3..aa379e70b3 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/109-test_pseudoelement_remains_at_end_of_selector.css +++ b/theme-compiler/tests/resources/sasslang/css/109-test_pseudoelement_remains_at_end_of_selector.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/110-test_redundant_selector_elimination.css b/theme-compiler/tests/resources/sasslang/css/110-test_redundant_selector_elimination.css index 7be91d143a..7be91d143a 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/110-test_redundant_selector_elimination.css +++ b/theme-compiler/tests/resources/sasslang/css/110-test_redundant_selector_elimination.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/112-test_target_with_child.css b/theme-compiler/tests/resources/sasslang/css/112-test_target_with_child.css index cee3a34a5a..cee3a34a5a 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/112-test_target_with_child.css +++ b/theme-compiler/tests/resources/sasslang/css/112-test_target_with_child.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/2-test_basic.css b/theme-compiler/tests/resources/sasslang/css/2-test_basic.css index 4504b8d829..4504b8d829 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/2-test_basic.css +++ b/theme-compiler/tests/resources/sasslang/css/2-test_basic.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/29-test_extend_does_not_warn_when_one_extension_fails_but_others_dont.css b/theme-compiler/tests/resources/sasslang/css/29-test_extend_does_not_warn_when_one_extension_fails_but_others_dont.css index 47d93c5dc1..47d93c5dc1 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/29-test_extend_does_not_warn_when_one_extension_fails_but_others_dont.css +++ b/theme-compiler/tests/resources/sasslang/css/29-test_extend_does_not_warn_when_one_extension_fails_but_others_dont.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/33-test_extend_redundancy_elimination_never_eliminates_base_selector.css b/theme-compiler/tests/resources/sasslang/css/33-test_extend_redundancy_elimination_never_eliminates_base_selector.css index 4a4aa6d222..4a4aa6d222 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/33-test_extend_redundancy_elimination_never_eliminates_base_selector.css +++ b/theme-compiler/tests/resources/sasslang/css/33-test_extend_redundancy_elimination_never_eliminates_base_selector.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/333-test_empty_content.css b/theme-compiler/tests/resources/sasslang/css/333-test_empty_content.css index f1c0f6c996..f1c0f6c996 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/333-test_empty_content.css +++ b/theme-compiler/tests/resources/sasslang/css/333-test_empty_content.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/35-test_extend_redundancy_elimination_when_it_would_reduce_specificity.css b/theme-compiler/tests/resources/sasslang/css/35-test_extend_redundancy_elimination_when_it_would_reduce_specificity.css index eb28eca8fa..eb28eca8fa 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/35-test_extend_redundancy_elimination_when_it_would_reduce_specificity.css +++ b/theme-compiler/tests/resources/sasslang/css/35-test_extend_redundancy_elimination_when_it_would_reduce_specificity.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/350-test_interpolation.css b/theme-compiler/tests/resources/sasslang/css/350-test_interpolation.css index 8b44646800..8b44646800 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/350-test_interpolation.css +++ b/theme-compiler/tests/resources/sasslang/css/350-test_interpolation.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/368-test_mixins_with_args.css b/theme-compiler/tests/resources/sasslang/css/368-test_mixins_with_args.css index 318a3f6ffb..318a3f6ffb 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/368-test_mixins_with_args.css +++ b/theme-compiler/tests/resources/sasslang/css/368-test_mixins_with_args.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/369-test_mixins_with_empty_args.css b/theme-compiler/tests/resources/sasslang/css/369-test_mixins_with_empty_args.css index 234d524066..234d524066 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/369-test_mixins_with_empty_args.css +++ b/theme-compiler/tests/resources/sasslang/css/369-test_mixins_with_empty_args.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/390-test_parent_selector_with_parent_and_subject.css b/theme-compiler/tests/resources/sasslang/css/390-test_parent_selector_with_parent_and_subject.css index 234fea7aa5..234fea7aa5 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/390-test_parent_selector_with_parent_and_subject.css +++ b/theme-compiler/tests/resources/sasslang/css/390-test_parent_selector_with_parent_and_subject.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/420-test_warn_directive.css b/theme-compiler/tests/resources/sasslang/css/420-test_warn_directive.css index 6d661f2404..6d661f2404 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/420-test_warn_directive.css +++ b/theme-compiler/tests/resources/sasslang/css/420-test_warn_directive.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/55-test_long_extendee.css b/theme-compiler/tests/resources/sasslang/css/55-test_long_extendee.css index 0d6bd2ec98..0d6bd2ec98 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/55-test_long_extendee.css +++ b/theme-compiler/tests/resources/sasslang/css/55-test_long_extendee.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/63-test_multiple_extendees.css b/theme-compiler/tests/resources/sasslang/css/63-test_multiple_extendees.css index d3fae7600f..d3fae7600f 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/63-test_multiple_extendees.css +++ b/theme-compiler/tests/resources/sasslang/css/63-test_multiple_extendees.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/65-test_multiple_extends_with_multiple_extenders_and_single_target.css b/theme-compiler/tests/resources/sasslang/css/65-test_multiple_extends_with_multiple_extenders_and_single_target.css index 44196e6602..44196e6602 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/65-test_multiple_extends_with_multiple_extenders_and_single_target.css +++ b/theme-compiler/tests/resources/sasslang/css/65-test_multiple_extends_with_multiple_extenders_and_single_target.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/66-test_multiple_extends_with_single_extender_and_single_target.css b/theme-compiler/tests/resources/sasslang/css/66-test_multiple_extends_with_single_extender_and_single_target.css index 9b5770d7c5..9b5770d7c5 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/66-test_multiple_extends_with_single_extender_and_single_target.css +++ b/theme-compiler/tests/resources/sasslang/css/66-test_multiple_extends_with_single_extender_and_single_target.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/67-test_multiple_targets.css b/theme-compiler/tests/resources/sasslang/css/67-test_multiple_targets.css index 779bd00f75..779bd00f75 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/67-test_multiple_targets.css +++ b/theme-compiler/tests/resources/sasslang/css/67-test_multiple_targets.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/7-test_combinator_unification_angle_sibling.css b/theme-compiler/tests/resources/sasslang/css/7-test_combinator_unification_angle_sibling.css index 657d1ec2f6..657d1ec2f6 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/7-test_combinator_unification_angle_sibling.css +++ b/theme-compiler/tests/resources/sasslang/css/7-test_combinator_unification_angle_sibling.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/70-test_nested_extender.css b/theme-compiler/tests/resources/sasslang/css/70-test_nested_extender.css index 1c4e604b71..1c4e604b71 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/70-test_nested_extender.css +++ b/theme-compiler/tests/resources/sasslang/css/70-test_nested_extender.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/80-test_nested_extender_merges_with_same_selector.css b/theme-compiler/tests/resources/sasslang/css/80-test_nested_extender_merges_with_same_selector.css index d1a50d50e3..d1a50d50e3 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/80-test_nested_extender_merges_with_same_selector.css +++ b/theme-compiler/tests/resources/sasslang/css/80-test_nested_extender_merges_with_same_selector.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/81-test_nested_extender_runs_unification.css b/theme-compiler/tests/resources/sasslang/css/81-test_nested_extender_runs_unification.css index 9aa8d14958..9aa8d14958 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/81-test_nested_extender_runs_unification.css +++ b/theme-compiler/tests/resources/sasslang/css/81-test_nested_extender_runs_unification.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/85-test_nested_extender_with_child_selector.css b/theme-compiler/tests/resources/sasslang/css/85-test_nested_extender_with_child_selector.css index f7bd620245..f7bd620245 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/85-test_nested_extender_with_child_selector.css +++ b/theme-compiler/tests/resources/sasslang/css/85-test_nested_extender_with_child_selector.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/86-test_nested_extender_with_child_selector_merges_with_same_selector.css b/theme-compiler/tests/resources/sasslang/css/86-test_nested_extender_with_child_selector_merges_with_same_selector.css index 75561708b3..75561708b3 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/86-test_nested_extender_with_child_selector_merges_with_same_selector.css +++ b/theme-compiler/tests/resources/sasslang/css/86-test_nested_extender_with_child_selector_merges_with_same_selector.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/88-test_nested_extender_with_early_child_selectors_doesnt_subseq_them.css b/theme-compiler/tests/resources/sasslang/css/88-test_nested_extender_with_early_child_selectors_doesnt_subseq_them.css index 4285daf8dd..4285daf8dd 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/88-test_nested_extender_with_early_child_selectors_doesnt_subseq_them.css +++ b/theme-compiler/tests/resources/sasslang/css/88-test_nested_extender_with_early_child_selectors_doesnt_subseq_them.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/90-test_nested_extender_with_sibling_selector.css b/theme-compiler/tests/resources/sasslang/css/90-test_nested_extender_with_sibling_selector.css index e9fe832391..e9fe832391 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/90-test_nested_extender_with_sibling_selector.css +++ b/theme-compiler/tests/resources/sasslang/css/90-test_nested_extender_with_sibling_selector.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/91-test_nested_selector_with_child_selector_hack_extendee.css b/theme-compiler/tests/resources/sasslang/css/91-test_nested_selector_with_child_selector_hack_extendee.css index 5556837892..5556837892 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/91-test_nested_selector_with_child_selector_hack_extendee.css +++ b/theme-compiler/tests/resources/sasslang/css/91-test_nested_selector_with_child_selector_hack_extendee.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/96-test_nested_target.css b/theme-compiler/tests/resources/sasslang/css/96-test_nested_target.css index d1a50d50e3..d1a50d50e3 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/96-test_nested_target.css +++ b/theme-compiler/tests/resources/sasslang/css/96-test_nested_target.css diff --git a/theme-compiler/tests/resources/sasslangbroken/css/98-test_not_remains_at_end_of_selector.css b/theme-compiler/tests/resources/sasslang/css/98-test_not_remains_at_end_of_selector.css index 540e6f8bf4..540e6f8bf4 100644 --- a/theme-compiler/tests/resources/sasslangbroken/css/98-test_not_remains_at_end_of_selector.css +++ b/theme-compiler/tests/resources/sasslang/css/98-test_not_remains_at_end_of_selector.css diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/106-test_pseudoclass_remains_at_end_of_selector.scss b/theme-compiler/tests/resources/sasslang/scss/106-test_pseudoclass_remains_at_end_of_selector.scss index 619bbb51cd..619bbb51cd 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/106-test_pseudoclass_remains_at_end_of_selector.scss +++ b/theme-compiler/tests/resources/sasslang/scss/106-test_pseudoclass_remains_at_end_of_selector.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/107-test_pseudoelement_goes_lefter_than_not.scss b/theme-compiler/tests/resources/sasslang/scss/107-test_pseudoelement_goes_lefter_than_not.scss index f50ad04b12..f50ad04b12 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/107-test_pseudoelement_goes_lefter_than_not.scss +++ b/theme-compiler/tests/resources/sasslang/scss/107-test_pseudoelement_goes_lefter_than_not.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/108-test_pseudoelement_goes_lefter_than_pseudoclass.scss b/theme-compiler/tests/resources/sasslang/scss/108-test_pseudoelement_goes_lefter_than_pseudoclass.scss index 230f925a10..230f925a10 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/108-test_pseudoelement_goes_lefter_than_pseudoclass.scss +++ b/theme-compiler/tests/resources/sasslang/scss/108-test_pseudoelement_goes_lefter_than_pseudoclass.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/109-test_pseudoelement_remains_at_end_of_selector.scss b/theme-compiler/tests/resources/sasslang/scss/109-test_pseudoelement_remains_at_end_of_selector.scss index cd588ed24a..cd588ed24a 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/109-test_pseudoelement_remains_at_end_of_selector.scss +++ b/theme-compiler/tests/resources/sasslang/scss/109-test_pseudoelement_remains_at_end_of_selector.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/110-test_redundant_selector_elimination.scss b/theme-compiler/tests/resources/sasslang/scss/110-test_redundant_selector_elimination.scss index ab8ba4845f..ab8ba4845f 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/110-test_redundant_selector_elimination.scss +++ b/theme-compiler/tests/resources/sasslang/scss/110-test_redundant_selector_elimination.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/112-test_target_with_child.scss b/theme-compiler/tests/resources/sasslang/scss/112-test_target_with_child.scss index 3748f64233..3748f64233 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/112-test_target_with_child.scss +++ b/theme-compiler/tests/resources/sasslang/scss/112-test_target_with_child.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/2-test_basic.scss b/theme-compiler/tests/resources/sasslang/scss/2-test_basic.scss index 9f3cde0011..9f3cde0011 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/2-test_basic.scss +++ b/theme-compiler/tests/resources/sasslang/scss/2-test_basic.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/29-test_extend_does_not_warn_when_one_extension_fails_but_others_dont.scss b/theme-compiler/tests/resources/sasslang/scss/29-test_extend_does_not_warn_when_one_extension_fails_but_others_dont.scss index a5a0dff1d0..a5a0dff1d0 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/29-test_extend_does_not_warn_when_one_extension_fails_but_others_dont.scss +++ b/theme-compiler/tests/resources/sasslang/scss/29-test_extend_does_not_warn_when_one_extension_fails_but_others_dont.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/33-test_extend_redundancy_elimination_never_eliminates_base_selector.scss b/theme-compiler/tests/resources/sasslang/scss/33-test_extend_redundancy_elimination_never_eliminates_base_selector.scss index ac6ad58994..ac6ad58994 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/33-test_extend_redundancy_elimination_never_eliminates_base_selector.scss +++ b/theme-compiler/tests/resources/sasslang/scss/33-test_extend_redundancy_elimination_never_eliminates_base_selector.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/333-test_empty_content.scss b/theme-compiler/tests/resources/sasslang/scss/333-test_empty_content.scss index ad8df41f25..ad8df41f25 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/333-test_empty_content.scss +++ b/theme-compiler/tests/resources/sasslang/scss/333-test_empty_content.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/35-test_extend_redundancy_elimination_when_it_would_reduce_specificity.scss b/theme-compiler/tests/resources/sasslang/scss/35-test_extend_redundancy_elimination_when_it_would_reduce_specificity.scss index 30a9d092cb..30a9d092cb 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/35-test_extend_redundancy_elimination_when_it_would_reduce_specificity.scss +++ b/theme-compiler/tests/resources/sasslang/scss/35-test_extend_redundancy_elimination_when_it_would_reduce_specificity.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/350-test_interpolation.scss b/theme-compiler/tests/resources/sasslang/scss/350-test_interpolation.scss index bb9c9a2c8f..bb9c9a2c8f 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/350-test_interpolation.scss +++ b/theme-compiler/tests/resources/sasslang/scss/350-test_interpolation.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/368-test_mixins_with_args.scss b/theme-compiler/tests/resources/sasslang/scss/368-test_mixins_with_args.scss index 3ba39ecac2..3ba39ecac2 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/368-test_mixins_with_args.scss +++ b/theme-compiler/tests/resources/sasslang/scss/368-test_mixins_with_args.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/369-test_mixins_with_empty_args.scss b/theme-compiler/tests/resources/sasslang/scss/369-test_mixins_with_empty_args.scss index f608979293..f608979293 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/369-test_mixins_with_empty_args.scss +++ b/theme-compiler/tests/resources/sasslang/scss/369-test_mixins_with_empty_args.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/390-test_parent_selector_with_parent_and_subject.scss b/theme-compiler/tests/resources/sasslang/scss/390-test_parent_selector_with_parent_and_subject.scss index 646238f379..646238f379 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/390-test_parent_selector_with_parent_and_subject.scss +++ b/theme-compiler/tests/resources/sasslang/scss/390-test_parent_selector_with_parent_and_subject.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/420-test_warn_directive.scss b/theme-compiler/tests/resources/sasslang/scss/420-test_warn_directive.scss index 53546355cc..53546355cc 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/420-test_warn_directive.scss +++ b/theme-compiler/tests/resources/sasslang/scss/420-test_warn_directive.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/55-test_long_extendee.scss b/theme-compiler/tests/resources/sasslang/scss/55-test_long_extendee.scss index 26ab65d344..26ab65d344 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/55-test_long_extendee.scss +++ b/theme-compiler/tests/resources/sasslang/scss/55-test_long_extendee.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/63-test_multiple_extendees.scss b/theme-compiler/tests/resources/sasslang/scss/63-test_multiple_extendees.scss index 2c0f5aa72a..2c0f5aa72a 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/63-test_multiple_extendees.scss +++ b/theme-compiler/tests/resources/sasslang/scss/63-test_multiple_extendees.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/65-test_multiple_extends_with_multiple_extenders_and_single_target.scss b/theme-compiler/tests/resources/sasslang/scss/65-test_multiple_extends_with_multiple_extenders_and_single_target.scss index 4c2a4c59f8..4c2a4c59f8 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/65-test_multiple_extends_with_multiple_extenders_and_single_target.scss +++ b/theme-compiler/tests/resources/sasslang/scss/65-test_multiple_extends_with_multiple_extenders_and_single_target.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/66-test_multiple_extends_with_single_extender_and_single_target.scss b/theme-compiler/tests/resources/sasslang/scss/66-test_multiple_extends_with_single_extender_and_single_target.scss index 48d9c5b733..48d9c5b733 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/66-test_multiple_extends_with_single_extender_and_single_target.scss +++ b/theme-compiler/tests/resources/sasslang/scss/66-test_multiple_extends_with_single_extender_and_single_target.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/67-test_multiple_targets.scss b/theme-compiler/tests/resources/sasslang/scss/67-test_multiple_targets.scss index fdcba65999..fdcba65999 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/67-test_multiple_targets.scss +++ b/theme-compiler/tests/resources/sasslang/scss/67-test_multiple_targets.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/7-test_combinator_unification_angle_sibling.scss b/theme-compiler/tests/resources/sasslang/scss/7-test_combinator_unification_angle_sibling.scss index b0120ac34e..b0120ac34e 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/7-test_combinator_unification_angle_sibling.scss +++ b/theme-compiler/tests/resources/sasslang/scss/7-test_combinator_unification_angle_sibling.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/70-test_nested_extender.scss b/theme-compiler/tests/resources/sasslang/scss/70-test_nested_extender.scss index 6245cdfda7..6245cdfda7 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/70-test_nested_extender.scss +++ b/theme-compiler/tests/resources/sasslang/scss/70-test_nested_extender.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/80-test_nested_extender_merges_with_same_selector.scss b/theme-compiler/tests/resources/sasslang/scss/80-test_nested_extender_merges_with_same_selector.scss index d959cce374..d959cce374 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/80-test_nested_extender_merges_with_same_selector.scss +++ b/theme-compiler/tests/resources/sasslang/scss/80-test_nested_extender_merges_with_same_selector.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/81-test_nested_extender_runs_unification.scss b/theme-compiler/tests/resources/sasslang/scss/81-test_nested_extender_runs_unification.scss index 32c2c0cc62..32c2c0cc62 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/81-test_nested_extender_runs_unification.scss +++ b/theme-compiler/tests/resources/sasslang/scss/81-test_nested_extender_runs_unification.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/85-test_nested_extender_with_child_selector.scss b/theme-compiler/tests/resources/sasslang/scss/85-test_nested_extender_with_child_selector.scss index da249ad564..da249ad564 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/85-test_nested_extender_with_child_selector.scss +++ b/theme-compiler/tests/resources/sasslang/scss/85-test_nested_extender_with_child_selector.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/86-test_nested_extender_with_child_selector_merges_with_same_selector.scss b/theme-compiler/tests/resources/sasslang/scss/86-test_nested_extender_with_child_selector_merges_with_same_selector.scss index 224945cd71..224945cd71 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/86-test_nested_extender_with_child_selector_merges_with_same_selector.scss +++ b/theme-compiler/tests/resources/sasslang/scss/86-test_nested_extender_with_child_selector_merges_with_same_selector.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/88-test_nested_extender_with_early_child_selectors_doesnt_subseq_them.scss b/theme-compiler/tests/resources/sasslang/scss/88-test_nested_extender_with_early_child_selectors_doesnt_subseq_them.scss index f2b8c6c07b..f2b8c6c07b 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/88-test_nested_extender_with_early_child_selectors_doesnt_subseq_them.scss +++ b/theme-compiler/tests/resources/sasslang/scss/88-test_nested_extender_with_early_child_selectors_doesnt_subseq_them.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/90-test_nested_extender_with_sibling_selector.scss b/theme-compiler/tests/resources/sasslang/scss/90-test_nested_extender_with_sibling_selector.scss index b9d495ce76..b9d495ce76 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/90-test_nested_extender_with_sibling_selector.scss +++ b/theme-compiler/tests/resources/sasslang/scss/90-test_nested_extender_with_sibling_selector.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/91-test_nested_selector_with_child_selector_hack_extendee.scss b/theme-compiler/tests/resources/sasslang/scss/91-test_nested_selector_with_child_selector_hack_extendee.scss index 928bc64f93..928bc64f93 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/91-test_nested_selector_with_child_selector_hack_extendee.scss +++ b/theme-compiler/tests/resources/sasslang/scss/91-test_nested_selector_with_child_selector_hack_extendee.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/96-test_nested_target.scss b/theme-compiler/tests/resources/sasslang/scss/96-test_nested_target.scss index 6662dea791..6662dea791 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/96-test_nested_target.scss +++ b/theme-compiler/tests/resources/sasslang/scss/96-test_nested_target.scss diff --git a/theme-compiler/tests/resources/sasslangbroken/scss/98-test_not_remains_at_end_of_selector.scss b/theme-compiler/tests/resources/sasslang/scss/98-test_not_remains_at_end_of_selector.scss index c1af8b1b2a..c1af8b1b2a 100644 --- a/theme-compiler/tests/resources/sasslangbroken/scss/98-test_not_remains_at_end_of_selector.scss +++ b/theme-compiler/tests/resources/sasslang/scss/98-test_not_remains_at_end_of_selector.scss diff --git a/theme-compiler/tests/src/com/vaadin/sass/AbstractTestBase.java b/theme-compiler/tests/src/com/vaadin/sass/AbstractTestBase.java index d867e6ccd0..01187b4502 100644 --- a/theme-compiler/tests/src/com/vaadin/sass/AbstractTestBase.java +++ b/theme-compiler/tests/src/com/vaadin/sass/AbstractTestBase.java @@ -30,6 +30,8 @@ import com.vaadin.sass.internal.ScssStylesheet; public abstract class AbstractTestBase { + public static final String CR = "\r"; + protected ScssStylesheet stylesheet; protected String originalScss; protected String parsedScss; @@ -69,17 +71,21 @@ public abstract class AbstractTestBase { public void testParser(String file) throws CSSException, IOException, URISyntaxException { originalScss = getFileContent(file); + originalScss = originalScss.replaceAll(CR, ""); ScssStylesheet sheet = getStyleSheet(file); parsedScss = sheet.toString(); + parsedScss = parsedScss.replace(CR, ""); Assert.assertEquals("Original CSS and parsed CSS do not match", originalScss, parsedScss); } public void testCompiler(String scss, String css) throws Exception { comparisonCss = getFileContent(css); + comparisonCss = comparisonCss.replaceAll(CR, ""); ScssStylesheet sheet = getStyleSheet(scss); sheet.compile(); parsedScss = sheet.toString(); + parsedScss = parsedScss.replaceAll(CR, ""); Assert.assertEquals("Original CSS and parsed CSS do not match", comparisonCss, parsedScss); } diff --git a/theme-compiler/tests/src/com/vaadin/sass/internal/expression/ArithmeticExpressionEvaluatorTest.java b/theme-compiler/tests/src/com/vaadin/sass/internal/expression/ArithmeticExpressionEvaluatorTest.java index 8978eb812e..c408255d0e 100644 --- a/theme-compiler/tests/src/com/vaadin/sass/internal/expression/ArithmeticExpressionEvaluatorTest.java +++ b/theme-compiler/tests/src/com/vaadin/sass/internal/expression/ArithmeticExpressionEvaluatorTest.java @@ -19,6 +19,7 @@ import org.junit.Assert; import org.junit.Test; import org.w3c.css.sac.LexicalUnit; +import com.vaadin.sass.internal.expression.exception.ArithmeticException; import com.vaadin.sass.internal.expression.exception.IncompatibleUnitsException; import com.vaadin.sass.internal.parser.LexicalUnitImpl; @@ -122,4 +123,15 @@ public class ArithmeticExpressionEvaluatorTest { Assert.assertEquals(LexicalUnit.SAC_CENTIMETER, result.getLexicalUnitType()); } + + @Test(expected = ArithmeticException.class) + public void testNonExistingSignal() { + LexicalUnitImpl operand2Integer = LexicalUnitImpl.createInteger(2, 3, + null, 2); + LexicalUnitImpl operatorComma = LexicalUnitImpl.createComma(2, 3, + operand2Integer); + LexicalUnitImpl operand3Integer = LexicalUnitImpl.createInteger(2, 3, + operatorComma, 3); + LexicalUnitImpl result = evaluator.evaluate(operand2Integer); + } } diff --git a/theme-compiler/tests/src/com/vaadin/sass/testcases/css/Media.java b/theme-compiler/tests/src/com/vaadin/sass/testcases/css/Media.java index 1c84bf8c49..b7ca325aa7 100644 --- a/theme-compiler/tests/src/com/vaadin/sass/testcases/css/Media.java +++ b/theme-compiler/tests/src/com/vaadin/sass/testcases/css/Media.java @@ -33,4 +33,5 @@ public class Media extends AbstractTestBase { IOException { testParser(css); } + } diff --git a/theme-compiler/tests/src/com/vaadin/sass/testcases/scss/CompassImports.java b/theme-compiler/tests/src/com/vaadin/sass/testcases/scss/CompassImports.java index 1e3eb09f0c..4e87eb2197 100644 --- a/theme-compiler/tests/src/com/vaadin/sass/testcases/scss/CompassImports.java +++ b/theme-compiler/tests/src/com/vaadin/sass/testcases/scss/CompassImports.java @@ -68,12 +68,14 @@ public class CompassImports extends AbstractTestBase { public void testCompiler(String scss, String css, String additionalPath) throws Exception { comparisonCss = getFileContent(css); + comparisonCss = comparisonCss.replaceAll(CR, ""); ScssStylesheet sheet = getStyleSheet(scss); Assert.assertNotNull(sheet); sheet.addResolver(new FilesystemResolver(additionalPath)); sheet.compile(); parsedScss = sheet.toString(); + parsedScss = parsedScss.replaceAll(CR, ""); Assert.assertEquals("Original CSS and parsed CSS do not match", comparisonCss, parsedScss); } diff --git a/uitest/ivy.xml b/uitest/ivy.xml index 9c86b2b68c..6270ec54de 100644 --- a/uitest/ivy.xml +++ b/uitest/ivy.xml @@ -83,7 +83,10 @@ <dependency org="org.hsqldb" name="hsqldb" rev="2.2.6" conf="build,ide -> default" /> <dependency org="com.vaadin" name="vaadin-testbench" - rev="3.1.1" conf="build-provided,ide -> default" /> + rev="3.1.2" conf="build-provided,ide -> default" /> + <!-- This should be removed once tests have been updated to use lang3 --> + <dependency org="commons-lang" name="commons-lang" + rev="2.6" conf="build,ide -> default" /> </dependencies> </ivy-module> diff --git a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java index a2f3c59f07..47d3a19fde 100644 --- a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java +++ b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java @@ -280,7 +280,7 @@ public class ApplicationRunnerServlet extends LegacyVaadinServlet { } - throw new ClassNotFoundException(); + throw new ClassNotFoundException(baseName); } private Logger getLogger() { diff --git a/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java b/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java index a8d639cbc8..20e187c187 100644 --- a/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java +++ b/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java @@ -217,7 +217,6 @@ public class DevelopmentServerLauncher { Socket accept = serverSocket.accept(); // First stop listening to the port serverSocket.close(); - final Thread stopThread = Thread.currentThread(); // Start a thread that kills the JVM if // server.stop() doesn't have any effect diff --git a/uitest/src/com/vaadin/tests/application/calculator/Calc.java b/uitest/src/com/vaadin/tests/application/calculator/Calc.java new file mode 100644 index 0000000000..7911556f4e --- /dev/null +++ b/uitest/src/com/vaadin/tests/application/calculator/Calc.java @@ -0,0 +1,268 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.application.calculator; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.ColumnHeaderMode; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +@SuppressWarnings("serial") +public class Calc extends AbstractTestUI { + + private class Log extends VerticalLayout { + + private Table table; + private Button addCommentButton; + private int line = 0; + + public Log() { + super(); + + table = new Table(); + table.setSizeFull(); + + setWidth("200px"); + setHeight("100%"); + + table.setColumnHeaderMode(ColumnHeaderMode.HIDDEN); + table.addContainerProperty("Operation", String.class, ""); + + addComponent(table); + + addCommentButton = new Button("Add Comment"); + addCommentButton.setWidth("100%"); + + addCommentButton.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + + final Window w = new Window("Add comment"); + VerticalLayout vl = new VerticalLayout(); + vl.setMargin(true); + + final TextField tf = new TextField(); + tf.setSizeFull(); + vl.addComponent(tf); + + HorizontalLayout hl = new HorizontalLayout(); + + Button okButton = new Button("OK"); + okButton.setWidth("100%"); + okButton.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + addRow("[ " + tf.getValue() + " ]"); + tf.setValue(""); + w.close(); + removeWindow(w); + } + }); + + Button cancelButton = new Button("Cancel"); + cancelButton.setWidth("100%"); + cancelButton.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + tf.setValue(""); + w.close(); + removeWindow(w); + } + }); + + hl.addComponent(cancelButton); + hl.addComponent(okButton); + hl.setSpacing(true); + hl.setWidth("100%"); + + vl.addComponent(hl); + vl.setSpacing(true); + + w.setContent(vl); + addWindow(w); + } + }); + + addComponent(addCommentButton); + + setExpandRatio(table, 1); + setSpacing(true); + } + + public void addRow(String row) { + Integer id = ++line; + table.addItem(new Object[] { row }, id); + table.setCurrentPageFirstItemIndex(line + 1); + } + + } + + // All variables are automatically stored in the session. + private Double current = 0.0; + private double stored = 0.0; + private char lastOperationRequested = 'C'; + private VerticalLayout topLayout = new VerticalLayout(); + + // User interface components + private final TextField display = new TextField(); + + private final Log log = new Log(); + + // Calculator "business logic" implemented here to keep the example + // minimal + private double calculate(char requestedOperation) { + if ('0' <= requestedOperation && requestedOperation <= '9') { + if (current == null) { + current = 0.0; + } + current = current * 10 + + Double.parseDouble("" + requestedOperation); + return current; + } + + if (current == null) { + current = stored; + } + switch (lastOperationRequested) { + case '+': + stored += current; + break; + case '-': + stored -= current; + break; + case '/': + stored /= current; + break; + case '*': + stored *= current; + break; + default: + stored = current; + break; + } + + switch (requestedOperation) { + case '+': + log.addRow(current + " +"); + break; + case '-': + log.addRow(current + " -"); + break; + case '/': + log.addRow(current + " /"); + break; + case '*': + log.addRow(current + " x"); + break; + case '=': + log.addRow(current + " ="); + log.addRow("------------"); + log.addRow("" + stored); + break; + } + + lastOperationRequested = requestedOperation; + current = null; + if (requestedOperation == 'C') { + log.addRow("0.0"); + stored = 0.0; + } + return stored; + } + + @Override + protected void setup(VaadinRequest request) { + setContent(topLayout); + + // Create the main layout for our application (4 columns, 5 rows) + final GridLayout layout = new GridLayout(4, 5); + + topLayout.setMargin(true); + topLayout.setSpacing(true); + Label title = new Label("Calculator"); + topLayout.addComponent(title); + topLayout.addComponent(log); + + HorizontalLayout horizontalLayout = new HorizontalLayout(); + horizontalLayout.setSpacing(true); + horizontalLayout.addComponent(layout); + horizontalLayout.addComponent(log); + topLayout.addComponent(horizontalLayout); + + // Create a result label that over all 4 columns in the first row + layout.setSpacing(true); + layout.addComponent(display, 0, 0, 3, 0); + layout.setComponentAlignment(display, Alignment.MIDDLE_RIGHT); + display.setSizeFull(); + display.setId("display"); + display.setValue("0.0"); + + // The operations for the calculator in the order they appear on the + // screen (left to right, top to bottom) + String[] operations = new String[] { "7", "8", "9", "/", "4", "5", "6", + "*", "1", "2", "3", "-", "0", "=", "C", "+" }; + + for (String caption : operations) { + + // Create a button and use this application for event handling + Button button = new Button(caption); + button.setWidth("40px"); + button.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + // Get the button that was clicked + Button button = event.getButton(); + + // Get the requested operation from the button caption + char requestedOperation = button.getCaption().charAt(0); + + // Calculate the new value + double newValue = calculate(requestedOperation); + + // Update the result label with the new value + display.setValue("" + newValue); + } + }); + button.setId("button_" + caption); + + // Add the button to our main layout + layout.addComponent(button); + } + + } + + @Override + protected String getTestDescription() { + return "Provide test application for generic testing purposes"; + } + + @Override + protected Integer getTicketNumber() { + return 12444; + } + +} diff --git a/uitest/src/com/vaadin/tests/applicationservlet/NoApplicationClass.html b/uitest/src/com/vaadin/tests/applicationservlet/NoApplicationClass.html deleted file mode 100644 index 6ed410fdb6..0000000000 --- a/uitest/src/com/vaadin/tests/applicationservlet/NoApplicationClass.html +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://localhost:8888/" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/ClassThatIsNotPresent?restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>//pre[2]</td> - <td>*java.lang.InstantiationException: Failed to load application class: ClassThatIsNotPresent*</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/applicationservlet/NoApplicationClassTest.java b/uitest/src/com/vaadin/tests/applicationservlet/NoApplicationClassTest.java new file mode 100644 index 0000000000..9d1b052182 --- /dev/null +++ b/uitest/src/com/vaadin/tests/applicationservlet/NoApplicationClassTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.applicationservlet; + +import java.util.Collections; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class NoApplicationClassTest extends MultiBrowserTest { + + @Test + public void testInvalidApplicationClass() { + openTestURL(); + String exceptionMessage = getDriver().findElement(By.xpath("//pre[2]")) + .getText(); + Assert.assertTrue(exceptionMessage + .contains("ServletException: java.lang.ClassNotFoundException: ClassThatIsNotPresent")); + } + + @Override + public List<DesiredCapabilities> getBrowsersToTest() { + return Collections.singletonList(Browser.CHROME + .getDesiredCapabilities()); + } + + @Override + protected String getDeploymentPath() { + return "/run/ClassThatIsNotPresent"; + } +} diff --git a/uitest/src/com/vaadin/tests/browserfeatures/WebkitPositionAbsoluteScrollbarsTest.java b/uitest/src/com/vaadin/tests/browserfeatures/WebkitPositionAbsoluteScrollbarsTest.java new file mode 100644 index 0000000000..54fb7212ca --- /dev/null +++ b/uitest/src/com/vaadin/tests/browserfeatures/WebkitPositionAbsoluteScrollbarsTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.browserfeatures; + +import org.junit.Test; +import org.openqa.selenium.By; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class WebkitPositionAbsoluteScrollbarsTest extends MultiBrowserTest { + + @Override + protected String getDeploymentPath() { + return "/statictestfiles/browserfeatures/WebkitPositionAbsoluteScrollbars.html"; + } + + @Test + public void testWebkitScrollbarProblem() throws Exception { + openTestURL(); + getDriver().findElement(By.id("step1")).click(); + getDriver().findElement(By.id("step2")).click(); + getDriver().findElement(By.id("step3")).click(); + getDriver().findElement(By.id("step4")).click(); + compareScreen("no-scrollbars"); + } +} diff --git a/uitest/src/com/vaadin/tests/gwtadapter/componentlocator/TestDetachedNotPresent.html b/uitest/src/com/vaadin/tests/componentlocator/TestDetachedNotPresent.html index 24e5e992ca..24e5e992ca 100644 --- a/uitest/src/com/vaadin/tests/gwtadapter/componentlocator/TestDetachedNotPresent.html +++ b/uitest/src/com/vaadin/tests/componentlocator/TestDetachedNotPresent.html diff --git a/uitest/src/com/vaadin/tests/components/AbstractTestUI.java b/uitest/src/com/vaadin/tests/components/AbstractTestUI.java index 8f92ff3118..5c7076c07e 100644 --- a/uitest/src/com/vaadin/tests/components/AbstractTestUI.java +++ b/uitest/src/com/vaadin/tests/components/AbstractTestUI.java @@ -113,27 +113,27 @@ public abstract class AbstractTestUI extends UI { protected void setTransport(VaadinRequest request) { String transport = request.getParameter("transport"); PushConfiguration config = getPushConfiguration(); - PushMode mode = config.getPushMode(); if ("xhr".equals(transport)) { config.setPushMode(PushMode.DISABLED); } else if ("websocket".equals(transport)) { - if (!mode.isEnabled()) { - config.setPushMode(PushMode.AUTOMATIC); - } - config.setTransport(Transport.WEBSOCKET); - // Ensure no fallback is used - getPushConfiguration().setParameter( - PushConfigurationState.FALLBACK_TRANSPORT_PARAM, "none"); + enablePush(Transport.WEBSOCKET); } else if ("streaming".equals(transport)) { - if (!mode.isEnabled()) { - config.setPushMode(PushMode.AUTOMATIC); - } - config.setTransport(Transport.STREAMING); - // Ensure no fallback is used - getPushConfiguration().setParameter( - PushConfigurationState.FALLBACK_TRANSPORT_PARAM, "none"); + enablePush(Transport.STREAMING); + } else if ("long-polling".equals(transport)) { + enablePush(Transport.LONG_POLLING); + } + } + + protected void enablePush(Transport transport) { + PushConfiguration config = getPushConfiguration(); + if (!config.getPushMode().isEnabled()) { + config.setPushMode(PushMode.AUTOMATIC); } + config.setTransport(transport); + // Ensure no fallback is used + getPushConfiguration().setParameter( + PushConfigurationState.FALLBACK_TRANSPORT_PARAM, "none"); } private VerticalLayout layout; @@ -148,6 +148,10 @@ public abstract class AbstractTestUI extends UI { getLayout().addComponent(c); } + public void addComponents(Component... c) { + getLayout().addComponents(c); + } + public void removeComponent(Component c) { getLayout().removeComponent(c); } diff --git a/uitest/src/com/vaadin/tests/components/UnknownComponentConnector.java b/uitest/src/com/vaadin/tests/components/UnknownComponentConnector.java new file mode 100644 index 0000000000..b6358b6c56 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/UnknownComponentConnector.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.ui.AbstractComponent; + +public class UnknownComponentConnector extends AbstractTestUI { + + public static class ComponentWithoutConnector extends AbstractComponent { + + } + + @Override + protected void setup(VaadinRequest request) { + ComponentWithoutConnector component = new ComponentWithoutConnector(); + component.setId("no-connector-component"); + addComponent(component); + } + + @Override + protected String getTestDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected Integer getTicketNumber() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.html b/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.html deleted file mode 100644 index 20f0e8e71e..0000000000 --- a/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.html +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.UnknownComponentConnectorTest?restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentsUnknownComponentConnectorTest::/VVerticalLayout[0]/VVerticalLayout[0]/VUnknownComponent[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> - <td>Widgetset does not contain implementation for com.vaadin.tests.components.UnknownComponentConnectorTest.ComponentWithoutConnector. Check its component connector's @Connect mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions.</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.java b/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.java index ff113d631e..49a3c29e2d 100644 --- a/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.java +++ b/uitest/src/com/vaadin/tests/components/UnknownComponentConnectorTest.java @@ -13,33 +13,29 @@ * License for the specific language governing permissions and limitations under * the License. */ - package com.vaadin.tests.components; -import com.vaadin.server.VaadinRequest; -import com.vaadin.ui.AbstractComponent; - -public class UnknownComponentConnectorTest extends AbstractTestUI { +import static org.junit.Assert.assertTrue; - public static class ComponentWithoutConnector extends AbstractComponent { +import org.junit.Test; +import org.openqa.selenium.WebElement; - } - - @Override - protected void setup(VaadinRequest request) { - addComponent(new ComponentWithoutConnector()); - } +import com.vaadin.tests.tb3.MultiBrowserTest; - @Override - protected String getTestDescription() { - // TODO Auto-generated method stub - return null; - } - - @Override - protected Integer getTicketNumber() { - // TODO Auto-generated method stub - return null; +/** + * Tests that a user is notified about a missing component from the widgetset + */ +public class UnknownComponentConnectorTest extends MultiBrowserTest { + + @Test + public void testConnectorNotFoundInWidgetset() throws Exception { + openTestURL(); + WebElement component = vaadinElementById("no-connector-component"); + assertTrue(component + .getText() + .startsWith( + "Widgetset 'com.vaadin.DefaultWidgetSet' does not contain " + + "implementation for com.vaadin.tests.components.UnknownComponentConnector." + + "ComponentWithoutConnector.")); } - } diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSource.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSource.java new file mode 100644 index 0000000000..5e81750e58 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSource.java @@ -0,0 +1,114 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.calendar; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.vaadin.event.Action; +import com.vaadin.event.Action.Handler; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Calendar; +import com.vaadin.ui.Calendar.TimeFormat; +import com.vaadin.ui.Label; +import com.vaadin.ui.components.calendar.CalendarComponentEvents.EventResizeHandler; +import com.vaadin.ui.components.calendar.event.BasicEvent; +import com.vaadin.ui.components.calendar.event.CalendarEvent; +import com.vaadin.ui.components.calendar.event.CalendarEventProvider; + +public class CalendarActionEventSource extends AbstractTestUI { + + private Calendar calendar; + + @Override + protected void setup(VaadinRequest request) { + calendar = new Calendar(new CalendarEventProvider() { + + @Override + public List<com.vaadin.ui.components.calendar.event.CalendarEvent> getEvents( + Date startDate, Date endDate) { + + List<CalendarEvent> events = new ArrayList<CalendarEvent>(); + + CalendarEvent event = null; + try { + event = new BasicEvent("NAME", "TOOLTIP", + new SimpleDateFormat("yyyy-MM-dd hh:mm") + .parse("2013-01-01 07:00"), + new SimpleDateFormat("yyyy-MM-dd hh:mm") + .parse("2013-01-01 11:00")); + } catch (ParseException e) { + // Nothing to do + } + events.add(event); + + return events; + } + + }); + try { + calendar.setStartDate(new SimpleDateFormat("yyyy-MM-dd") + .parse("2013-01-01")); + calendar.setEndDate(new SimpleDateFormat("yyyy-MM-dd") + .parse("2013-01-31")); + } catch (ParseException e) { + // Nothing to do + } + calendar.setImmediate(true); + calendar.setFirstVisibleHourOfDay(6); + calendar.setLastVisibleHourOfDay(22); + calendar.setTimeFormat(TimeFormat.Format24H); + calendar.setHandler((EventResizeHandler) null); + + setEnabled(true); + calendar.addActionHandler(new Handler() { + @Override + public void handleAction(Action action, Object sender, Object target) { + Label label1 = new Label(calendar.toString()); + label1.setId("calendarlabel"); + addComponent(label1); + + Label label2 = new Label(sender.toString()); + label2.setId("senderlabel"); + addComponent(label2); + } + + @Override + public Action[] getActions(Object target, Object sender) { + return new Action[] { new Action("ACTION") }; + } + }); + addComponent(calendar); + calendar.setSizeFull(); + setSizeFull(); + + } + + @Override + protected String getTestDescription() { + return "Calendar action event source should be the calendar itself"; + } + + @Override + protected Integer getTicketNumber() { + return 13191; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSourceTest.java b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSourceTest.java new file mode 100644 index 0000000000..6fbe77040f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/calendar/CalendarActionEventSourceTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.calendar; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.tb3.PrivateTB3Configuration; + +/** + * Test that calendar action event source is the calendar, not a private nested + * class in it. + * + * The related code is not browser dependent so only running on a single + * browser. + * + * @author Vaadin Ltd + */ +public class CalendarActionEventSourceTest extends PrivateTB3Configuration { + @Test + public void testActionEventSourceIsCalendarForEmptyCell() throws Exception { + openTestURL(); + + // perform action on empty cell + WebElement element = getDriver().findElement( + By.className("v-calendar-spacer")); + performAction(element); + + checkEventSourceIsCalendar(); + } + + @Test + public void testActionEventSourceIsCalendarForEvent() throws Exception { + openTestURL(); + + // perform action on calendar event + WebElement element = getDriver().findElement( + By.className("v-calendar-event")); + performAction(element); + + checkEventSourceIsCalendar(); + } + + private void performAction(WebElement element) { + // right click + new Actions(getDriver()).contextClick(element).perform(); + WebElement menuItem = getDriver().findElement( + By.className("gwt-MenuItem")); + menuItem.click(); + } + + private void checkEventSourceIsCalendar() { + String calendarObject = getDriver().findElement(By.id("calendarlabel")) + .getText(); + String actionSourceObject = getDriver().findElement( + By.id("senderlabel")).getText(); + Assert.assertEquals( + "Calendar action event source must be the calendar itself", + calendarObject, actionSourceObject); + } + + @Override + protected Class<?> getUIClass() { + return CalendarActionEventSource.class; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/orderedlayout/NestedLayoutCaptionHover.java b/uitest/src/com/vaadin/tests/components/orderedlayout/NestedLayoutCaptionHover.java new file mode 100644 index 0000000000..e9b022eac2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/orderedlayout/NestedLayoutCaptionHover.java @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.orderedlayout; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.VerticalLayout; + +/** + * Test hovering over nested layout caption + * + * @author Vaadin Ltd + */ +public class NestedLayoutCaptionHover extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + VerticalLayout test = new VerticalLayout(); + test.setCaption("inner layout"); + addComponent(new VerticalLayout(new VerticalLayout(new VerticalLayout( + test)))); + } + + @Override + protected String getTestDescription() { + return "Hovering over nested layout caption should not freeze the browser"; + } + + @Override + protected Integer getTicketNumber() { + return 12469; + } +} diff --git a/uitest/src/com/vaadin/tests/components/orderedlayout/NestedLayoutCaptionHoverTest.java b/uitest/src/com/vaadin/tests/components/orderedlayout/NestedLayoutCaptionHoverTest.java new file mode 100644 index 0000000000..95a2c9f493 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/orderedlayout/NestedLayoutCaptionHoverTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.orderedlayout; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.HasInputDevices; +import org.openqa.selenium.interactions.internal.Coordinates; +import org.openqa.selenium.internal.Locatable; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests hovering over caption in nested layout + */ +public class NestedLayoutCaptionHoverTest extends MultiBrowserTest { + + @Test + public void testTooltipInNestedLayout() throws Exception { + openTestURL(); + + WebElement caption = getDriver().findElement( + By.className("v-captiontext")); + + assertEquals("inner layout", caption.getText()); + + // Hover over the caption + Coordinates coords = ((Locatable) caption).getCoordinates(); + ((HasInputDevices) getDriver()).getMouse().mouseMove(coords); + sleep(1000); + + // Verify that there's no error notification + WebElement error = vaadinElement("Root/VNotification[0]"); + assertNull("No error should be found", error); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/orderedlayout/NestedLayoutCaptionTooltip.html b/uitest/src/com/vaadin/tests/components/orderedlayout/NestedLayoutCaptionTooltip.html deleted file mode 100644 index 4f574a92c7..0000000000 --- a/uitest/src/com/vaadin/tests/components/orderedlayout/NestedLayoutCaptionTooltip.html +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.applicationcontext.CloseSession?restartApplication&debug</td> - <td></td> -</tr> -<!-- Show tooltip for the Events caption --> -<tr> - <td>showTooltip</td> - <td>//div[@id='gwt-uid-4']/span</td> - <td></td> -</tr> -<!-- Verify that there's no error notification --> -<tr> - <td>assertElementNotPresent</td> - <td>vaadin=runcomvaadintestsapplicationcontextCloseSession::Root/VNotification[0]</td> - <td></td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChanges.java b/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChanges.java new file mode 100644 index 0000000000..1e7d817094 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChanges.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.orderedlayout; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; + +public class VerticalLayoutFocusWithDOMChanges extends AbstractTestUI implements + ValueChangeListener { + + Button dummyButton = new Button("Just a button"); + TextField listenedTextField = new TextField(); + TextField changingTextField = new TextField(); + + @Override + protected void setup(VaadinRequest request) { + VerticalLayout content = new VerticalLayout(); + setSizeFull(); + listenedTextField.addValueChangeListener(this); + listenedTextField.setImmediate(true); + changingTextField.setImmediate(true); + content.addComponent(dummyButton); + content.addComponent(listenedTextField); + content.addComponent(changingTextField); + content.setMargin(true); + content.setSpacing(true); + setContent(content); + } + + @Override + protected String getTestDescription() { + return "Check that creating or removing caption wrap doesn't lose focus"; + } + + @Override + protected Integer getTicketNumber() { + return 12967; + } + + @Override + public void valueChange(ValueChangeEvent event) { + changingTextField.setRequired(!changingTextField.isRequired()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChangesTest.java b/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChangesTest.java new file mode 100644 index 0000000000..14c26a0e17 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/orderedlayout/VerticalLayoutFocusWithDOMChangesTest.java @@ -0,0 +1,100 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.orderedlayout; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.testbench.By; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class VerticalLayoutFocusWithDOMChangesTest extends MultiBrowserTest { + + private String initialText = "Some"; + private String incrementalText = " text"; + + @Test + public void inputTextAndChangeFocus() throws InterruptedException { + openTestURL(); + List<WebElement> textFields = getDriver().findElements( + By.tagName("input")); + WebElement tf1 = textFields.get(0); + WebElement tf2 = textFields.get(1); + tf1.sendKeys(initialText); + new Actions(getDriver()).moveToElement(tf2).click().build().perform(); + + WebElement activeElement = getFocusedElement(); + Assert.assertEquals("input", activeElement.getTagName()); + Assert.assertEquals("", activeElement.getAttribute("value")); + + tf1.sendKeys(incrementalText); + new Actions(getDriver()) + .moveToElement( + getDriver().findElement(By.className("v-button"))) + .click().build().perform(); + activeElement = getFocusedElement(); + Assert.assertEquals("Just a button", activeElement.getText()); + + DesiredCapabilities capabilities = getDesiredCapabilities(); + if (capabilities.equals(BrowserUtil.ie(8)) + || capabilities.equals(BrowserUtil.ie(9))) { + // IE8 and IE9 insert cursor in the start of input instead of end. + Assert.assertEquals(incrementalText + initialText, + tf1.getAttribute("value")); + } else { + Assert.assertEquals(initialText + incrementalText, + tf1.getAttribute("value")); + } + } + + @Test + public void moveFocusAndChangeFieldWithValue() { + openTestURL(); + List<WebElement> textFields = getDriver().findElements( + By.tagName("input")); + WebElement tf1 = textFields.get(0); + WebElement tf2 = textFields.get(1); + + String firstText = "This is"; + String secondText = " default value"; + + tf2.sendKeys(firstText); + tf1.sendKeys(initialText); + new Actions(getDriver()).moveToElement(tf2).click().build().perform(); + + WebElement activeElement = getFocusedElement(); + Assert.assertEquals("input", activeElement.getTagName()); + Assert.assertEquals(firstText, activeElement.getAttribute("value")); + + new Actions(getDriver()).sendKeys(secondText).build().perform(); + DesiredCapabilities capabilities = getDesiredCapabilities(); + if (capabilities.equals(BrowserUtil.ie(8)) + || capabilities.equals(BrowserUtil.ie(9))) { + // IE8 and IE9 insert cursor in the start of input instead of end. + Assert.assertEquals(secondText + firstText, + tf2.getAttribute("value")); + } else { + Assert.assertEquals(firstText + secondText, + tf2.getAttribute("value")); + } + } + +} diff --git a/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.html b/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.html new file mode 100644 index 0000000000..2f8532de61 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.html @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>SelectItemCaptionRefresh</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">SelectItemCaptionRefresh</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.select.SelectItemCaptionRefresh?restartApplication</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentsselectSelectItemCaptionRefresh::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VFilterSelect[0]#button</td> + <td>10,14</td> +</tr> +<tr> + <td>mouseClick</td> + <td>//div[@id='VAADIN_COMBOBOX_OPTIONLIST']/div/div[2]/table/tbody/tr[2]/td/span</td> + <td>16,11</td> +</tr> +<tr> + <td>verifyValue</td> + <td>vaadin=runcomvaadintestscomponentsselectSelectItemCaptionRefresh::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VFilterSelect[0]#textbox</td> + <td>start</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsselectSelectItemCaptionRefresh::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>verifyValue</td> + <td>vaadin=runcomvaadintestscomponentsselectSelectItemCaptionRefresh::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VFilterSelect[0]#textbox</td> + <td>0</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.java b/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.java new file mode 100644 index 0000000000..de068ed230 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/select/SelectItemCaptionRefresh.java @@ -0,0 +1,75 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.select; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Select; + +public class SelectItemCaptionRefresh extends AbstractTestUI { + + final Object itemId = new Object(); + Select select; + + Button.ClickListener clickListener = new Button.ClickListener() { + Integer i = Integer.valueOf(0); + + @Override + public void buttonClick(final ClickEvent event) { + select.setItemCaption(itemId, (i++).toString()); + } + }; + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server. + * VaadinRequest) + */ + @Override + protected void setup(VaadinRequest request) { + select = new Select("Foo"); + + select.addItem(itemId); + select.setItemCaption(itemId, "start"); + + addComponent(select); + addComponent(new Button("Update item's caption", clickListener)); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription() + */ + @Override + protected String getTestDescription() { + return "Selected option should be updated when item caption changes in the Select."; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber() + */ + @Override + protected Integer getTicketNumber() { + return 9250; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/table/ExpandingContainer.java b/uitest/src/com/vaadin/tests/components/table/ExpandingContainer.java new file mode 100644 index 0000000000..829c29b95b --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/ExpandingContainer.java @@ -0,0 +1,429 @@ +package com.vaadin.tests.components.table; + +import java.util.AbstractList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.logging.Logger; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.AbstractContainer; +import com.vaadin.data.util.BeanItem; +import com.vaadin.server.VaadinSession; +import com.vaadin.ui.Component; +import com.vaadin.ui.Label; + +@SuppressWarnings("serial") +public class ExpandingContainer extends AbstractContainer implements + Container.Ordered, Container.Indexed, Container.ItemSetChangeNotifier { + + public static final List<String> PROPERTY_IDS = Arrays.asList("id", + "column1", "column2"); + + private final Label sizeLabel; + private final Logger log = Logger.getLogger(this.getClass().getName()); + + private int currentSize = 300; + + private boolean loggingEnabled; + + public ExpandingContainer(Label sizeLabel) { + this.sizeLabel = sizeLabel; + updateLabel(); + } + + private void log(String message) { + if (loggingEnabled) { + log.info(message); + } + } + + // Expand container if we scroll past 85% + public int checkExpand(int index) { + log("checkExpand(" + index + ")"); + if (index >= currentSize * 0.85) { + final int oldsize = currentSize; + currentSize = (int) (oldsize * 1.3333); + log("*** getSizeWithHint(" + index + "): went past 85% of size=" + + oldsize + ", new size=" + currentSize); + updateLabel(); + } + return currentSize; + }; + + @Override + public void fireItemSetChange() { + super.fireItemSetChange(); + } + + private void updateLabel() { + sizeLabel.setValue("Container size: " + currentSize); + } + + public void triggerItemSetChange() { + log("*** triggerItemSetChange(): scheduling item set change event"); + final VaadinSession session = VaadinSession.getCurrent(); + new Thread() { + @Override + public void run() { + ExpandingContainer.this.invoke(session, new Runnable() { + @Override + public void run() { + log("*** Firing item set change event"); + ExpandingContainer.this.fireItemSetChange(); + } + }); + } + }.start(); + } + + private void invoke(VaadinSession session, Runnable action) { + session.lock(); + VaadinSession previousSession = VaadinSession.getCurrent(); + VaadinSession.setCurrent(session); + try { + action.run(); + } finally { + session.unlock(); + VaadinSession.setCurrent(previousSession); + } + } + + // Container + + @Override + public BeanItem<MyBean> getItem(Object itemId) { + if (!(itemId instanceof Integer)) { + return null; + } + final int index = ((Integer) itemId).intValue(); + return new BeanItem<MyBean>(new MyBean(index)); + } + + @Override + public Collection<Integer> getItemIds() { + return new IntList(size()); + } + + @Override + public List<String> getContainerPropertyIds() { + return PROPERTY_IDS; + } + + @Override + @SuppressWarnings("rawtypes") + public Property/* <?> */getContainerProperty(Object itemId, + Object propertyId) { + BeanItem<MyBean> item = getItem(itemId); + return item != null ? item.getItemProperty(propertyId) : null; + } + + @Override + public Class<?> getType(Object propertyId) { + return Component.class; + } + + @Override + public int size() { + return currentSize; + } + + @Override + public boolean containsId(Object itemId) { + if (!(itemId instanceof Integer)) { + return false; + } + int index = ((Integer) itemId).intValue(); + checkExpand(index); + return index >= 0 && index < currentSize; + } + + /** + * @throws UnsupportedOperationException + * always + */ + @Override + public Item addItem(Object itemId) { + throw new UnsupportedOperationException(); + } + + /** + * @throws UnsupportedOperationException + * always + */ + @Override + public Item addItem() { + throw new UnsupportedOperationException(); + } + + /** + * @throws UnsupportedOperationException + * always + */ + @Override + public boolean removeItem(Object itemId) { + throw new UnsupportedOperationException(); + } + + /** + * @throws UnsupportedOperationException + * always + */ + @Override + public boolean addContainerProperty(Object propertyId, Class<?> type, + Object defaultValue) { + throw new UnsupportedOperationException(); + } + + /** + * @throws UnsupportedOperationException + * always + */ + @Override + public boolean removeContainerProperty(Object propertyId) { + throw new UnsupportedOperationException(); + } + + /** + * @throws UnsupportedOperationException + * always + */ + @Override + public boolean removeAllItems() { + throw new UnsupportedOperationException(); + } + + // Container.Indexed + + /** + * @throws UnsupportedOperationException + * always + */ + @Override + public Object addItemAt(int index) { + throw new UnsupportedOperationException(); + } + + /** + * @throws UnsupportedOperationException + * always + */ + @Override + public Item addItemAt(int index, Object newItemId) { + throw new UnsupportedOperationException(); + } + + @Override + public Integer getIdByIndex(int index) { + if (index < 0) { + throw new IndexOutOfBoundsException("index < " + index); + } + final int size = currentSize; + if (index >= size) { + throw new IndexOutOfBoundsException("index=" + index + " but size=" + + size); + } + checkExpand(index); + return index; + } + + @Override + public List<Integer> getItemIds(int startIndex, int numberOfItems) { + if (numberOfItems < 0) { + throw new IllegalArgumentException("numberOfItems < 0"); + } + final int size = currentSize; + checkExpand(startIndex); + if (startIndex < 0 || startIndex > size) { + throw new IndexOutOfBoundsException("startIndex=" + startIndex + + " but size=" + size); + } + if (startIndex + numberOfItems > size) { + numberOfItems = size - startIndex; + } + return new IntList(startIndex, numberOfItems); + } + + @Override + public int indexOfId(Object itemId) { + if (!(itemId instanceof Integer)) { + return -1; + } + final int index = ((Integer) itemId).intValue(); + checkExpand(index); + if (index < 0 || index >= currentSize) { + return -1; + } + return index; + } + + // Container.Ordered + + @Override + public Integer nextItemId(Object itemId) { + if (!(itemId instanceof Integer)) { + return null; + } + int index = ((Integer) itemId).intValue(); + checkExpand(index); + if (index < 0 || index + 1 >= currentSize) { + return null; + } + return index + 1; + } + + @Override + public Integer prevItemId(Object itemId) { + if (!(itemId instanceof Integer)) { + return null; + } + int index = ((Integer) itemId).intValue(); + checkExpand(index); + if (index - 1 < 0 || index >= currentSize) { + return null; + } + return index - 1; + } + + @Override + public Integer firstItemId() { + return currentSize == 0 ? null : 0; + } + + @Override + public Integer lastItemId() { + final int size = currentSize; + return size == 0 ? null : size - 1; + } + + @Override + public boolean isFirstId(Object itemId) { + if (!(itemId instanceof Integer)) { + return false; + } + final int index = ((Integer) itemId).intValue(); + checkExpand(index); + final int size = currentSize; + return size > 0 && index == 0; + } + + @Override + public boolean isLastId(Object itemId) { + if (!(itemId instanceof Integer)) { + return false; + } + int index = ((Integer) itemId).intValue(); + checkExpand(index); + int size = currentSize; + return size > 0 && index == size - 1; + } + + /** + * @throws UnsupportedOperationException + * always + */ + @Override + public Item addItemAfter(Object previousItemId) { + throw new UnsupportedOperationException(); + } + + /** + * @throws UnsupportedOperationException + * always + */ + @Override + public Item addItemAfter(Object previousItemId, Object newItemId) { + throw new UnsupportedOperationException(); + } + + // Container.ItemSetChangeNotifier + + @Override + @SuppressWarnings("deprecation") + public void addListener(Container.ItemSetChangeListener listener) { + super.addListener(listener); + } + + @Override + public void addItemSetChangeListener( + Container.ItemSetChangeListener listener) { + super.addItemSetChangeListener(listener); + } + + @Override + @SuppressWarnings("deprecation") + public void removeListener(Container.ItemSetChangeListener listener) { + super.removeListener(listener); + } + + @Override + public void removeItemSetChangeListener( + Container.ItemSetChangeListener listener) { + super.removeItemSetChangeListener(listener); + } + + // IntList + + private static class IntList extends AbstractList<Integer> { + + private final int min; + private final int size; + + public IntList(int size) { + this(0, size); + } + + public IntList(int min, int size) { + if (size < 0) { + throw new IllegalArgumentException("size < 0"); + } + this.min = min; + this.size = size; + } + + @Override + public int size() { + return size; + } + + @Override + public Integer get(int index) { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(); + } + return min + index; + } + } + + // MyBean + public class MyBean { + + private final int index; + + public MyBean(int index) { + this.index = index; + } + + public String getId() { + return "ROW #" + index; + } + + public String getColumn1() { + return genText(); + } + + public String getColumn2() { + return genText(); + } + + private String genText() { + return "this is a line of text in row #" + index; + } + } + + public void logDetails(boolean enabled) { + loggingEnabled = enabled; + } +} diff --git a/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceCondition.java b/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceCondition.java new file mode 100644 index 0000000000..8ad2d7f9c7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceCondition.java @@ -0,0 +1,67 @@ +package com.vaadin.tests.components.table; + +import java.util.Map; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.ui.Label; +import com.vaadin.ui.Table; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; + +@SuppressWarnings("serial") +public class ExpandingContainerVisibleRowRaceCondition extends UI { + + static final String TABLE = "table"; + + @Override + public void init(VaadinRequest request) { + final VerticalLayout rootLayout = new VerticalLayout(); + + rootLayout.setSpacing(true); + rootLayout.setSizeFull(); + rootLayout.setMargin(true); + + final Label sizeLabel = new Label(); + final ExpandingContainer container = new ExpandingContainer(sizeLabel); + container.logDetails(false); + + Table table = new Table(null, container) { + @Override + public void changeVariables(Object source, + Map<String, Object> variables) { + if (variables.containsKey("firstvisible")) { + int index = (Integer) variables.get("firstvisible"); + container.checkExpand(index); + } + if (variables.containsKey("reqfirstrow") + || variables.containsKey("reqrows")) { + try { + int index = ((Integer) variables + .get("lastToBeRendered")).intValue(); + container.checkExpand(index); + } catch (Exception e) { + // do nothing + } + } + super.changeVariables(source, variables); + } + }; + table.setId(TABLE); + table.setCacheRate(0); + table.setSizeFull(); + table.setVisibleColumns(ExpandingContainer.PROPERTY_IDS + .toArray(new String[ExpandingContainer.PROPERTY_IDS.size()])); + + table.setCurrentPageFirstItemIndex(120); + + rootLayout.addComponent(table); + rootLayout.setExpandRatio(table, 1); + + rootLayout.addComponent(sizeLabel); + + setContent(rootLayout); + + container.checkExpand(300); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceConditionTest.java b/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceConditionTest.java new file mode 100644 index 0000000000..73dd7b1f81 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceConditionTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.table; + +import static com.vaadin.tests.components.table.ExpandingContainerVisibleRowRaceCondition.TABLE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class ExpandingContainerVisibleRowRaceConditionTest extends + MultiBrowserTest { + + private static final int ROW_HEIGHT = 20; + + @Test + public void testScrollingWorksWithoutJumpingWhenItemSetChangeOccurs() { + openTestURL(); + sleep(1000); + + WebElement table = vaadinElementById(TABLE); + assertFirstRowIdIs("ROW #120"); + + testBenchElement(table.findElement(By.className("v-scrollable"))) + .scroll(320 * ROW_HEIGHT); + sleep(1000); + + assertRowIdIsInThePage("ROW #330"); + assertScrollPositionIsNotVisible(); + } + + @Override + protected void sleep(int milliseconds) { + try { + super.sleep(milliseconds); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private void assertFirstRowIdIs(String expected) { + List<WebElement> cellsOfFirstColumn = getCellsOfFirstColumn(); + WebElement first = cellsOfFirstColumn.get(0); + assertEquals(expected, first.getText()); + } + + private void assertRowIdIsInThePage(String expected) { + List<WebElement> cellsOfFirstColumn = getCellsOfFirstColumn(); + for (WebElement rowId : cellsOfFirstColumn) { + if (expected.equals(rowId.getText())) { + return; + } + } + fail("Expected row was not found"); + } + + private void assertScrollPositionIsNotVisible() { + WebElement table = vaadinElementById(TABLE); + WebElement scrollPosition = table.findElement(By + .className("v-table-scrollposition")); + assertFalse(scrollPosition.isDisplayed()); + } + + private List<WebElement> getCellsOfFirstColumn() { + WebElement table = vaadinElementById(TABLE); + List<WebElement> firstCellOfRows = table.findElements(By + .cssSelector(".v-table-table tr > td")); + return firstCellOfRows; + } +} diff --git a/uitest/src/com/vaadin/tests/components/table/SelectAllRows.java b/uitest/src/com/vaadin/tests/components/table/SelectAllRows.java new file mode 100644 index 0000000000..6007ea2984 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/SelectAllRows.java @@ -0,0 +1,83 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.table; + +import java.util.Set; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Label; +import com.vaadin.ui.Table; +import com.vaadin.ui.VerticalLayout; + +public class SelectAllRows extends AbstractTestUI { + + static final String TABLE = "table"; + static final String COUNT_SELECTED_BUTTON = "button"; + static final int TOTAL_NUMBER_OF_ROWS = 300; + static final String COUNT_OF_SELECTED_ROWS_LABEL = "label"; + + @Override + protected void setup(VaadinRequest request) { + VerticalLayout layout = new VerticalLayout(); + layout.setMargin(true); + layout.setSpacing(true); + setContent(layout); + + final Table table = new Table(); + table.setId(TABLE); + table.setImmediate(true); + table.setMultiSelect(true); + table.setSelectable(true); + table.addContainerProperty("row", String.class, null); + layout.addComponent(table); + + Button button = new Button("Count"); + button.setId(COUNT_SELECTED_BUTTON); + layout.addComponent(button); + + final Label label = new Label(); + label.setId(COUNT_OF_SELECTED_ROWS_LABEL); + label.setCaption("Selected count:"); + layout.addComponent(label); + + button.addClickListener(new Button.ClickListener() { + + @Override + public void buttonClick(Button.ClickEvent event) { + Set selected = (Set) table.getValue(); + label.setValue(String.valueOf(selected.size())); + } + }); + + for (int i = 0; i < TOTAL_NUMBER_OF_ROWS; i++) { + Object itemId = table.addItem(); + table.getContainerProperty(itemId, "row").setValue("row " + i); + } + } + + @Override + protected String getTestDescription() { + return "Selecting all rows does not work by selecting first row, press shift then select last row"; + } + + @Override + protected Integer getTicketNumber() { + return 13008; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/table/SelectAllRowsTest.java b/uitest/src/com/vaadin/tests/components/table/SelectAllRowsTest.java new file mode 100644 index 0000000000..664b36fa75 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/SelectAllRowsTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.table; + +import static com.vaadin.tests.components.table.SelectAllRows.COUNT_OF_SELECTED_ROWS_LABEL; +import static com.vaadin.tests.components.table.SelectAllRows.COUNT_SELECTED_BUTTON; +import static com.vaadin.tests.components.table.SelectAllRows.TABLE; +import static com.vaadin.tests.components.table.SelectAllRows.TOTAL_NUMBER_OF_ROWS; +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class SelectAllRowsTest extends MultiBrowserTest { + + private final static String TABLE_ROW = "v-table-row"; + + @Override + public List<DesiredCapabilities> getBrowsersToTest() { + // Pressing Shift modifier key does not work with TestBench and IE + // (#8621) + return Arrays.asList(Browser.FIREFOX.getDesiredCapabilities(), + Browser.CHROME.getDesiredCapabilities()); + } + + @Test + public void testAllRowsAreSelected() { + openTestURL(); + + selectAllRowsInTable(); + int selectedRows = countSelectedItems(); + + assertEquals(TOTAL_NUMBER_OF_ROWS, selectedRows); + } + + private int countSelectedItems() { + WebElement countButton = vaadinElementById(COUNT_SELECTED_BUTTON); + countButton.click(); + WebElement countOfSelectedRows = vaadinElementById(COUNT_OF_SELECTED_ROWS_LABEL); + String count = countOfSelectedRows.getText(); + return Integer.parseInt(count); + } + + private void selectAllRowsInTable() { + clickFirstRow(); + scrollTableToBottom(); + new Actions(getDriver()).keyDown(Keys.SHIFT).perform(); + clickLastRow(); + new Actions(getDriver()).keyUp(Keys.SHIFT).perform(); + } + + private void clickLastRow() { + List<WebElement> rows = allVisibleTableRows(); + WebElement lastRow = rows.get(rows.size() - 1); + lastRow.click(); + } + + private void clickFirstRow() { + WebElement firstRow = allVisibleTableRows().get(0); + firstRow.click(); + } + + private void scrollTableToBottom() { + WebElement table = vaadinElementById(TABLE); + testBenchElement(table.findElement(By.className("v-scrollable"))) + .scroll(TOTAL_NUMBER_OF_ROWS * 30); + + // Wait for scrolling to complete. Otherwise, clicking last row will + // fail with Chrome + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private List<WebElement> allVisibleTableRows() { + WebElement table = vaadinElementById(TABLE); + List<WebElement> rows = table.findElements(By + .cssSelector(".v-table-table tr")); + return rows; + } +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCalls.java b/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCalls.java index 6e4b62e4f7..ab0198f39c 100644 --- a/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCalls.java +++ b/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCalls.java @@ -16,26 +16,217 @@ package com.vaadin.tests.components.table; +import java.util.ArrayList; +import java.util.Collection; + +import org.json.JSONObject; + import com.vaadin.annotations.Push; -import com.vaadin.event.ItemClickEvent; -import com.vaadin.event.ItemClickEvent.ItemClickListener; +import com.vaadin.server.ClientConnector; +import com.vaadin.server.StreamVariable; import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.ConnectorTracker; import com.vaadin.ui.Table; @Push public class TableRemovedQuicklySendsInvalidRpcCalls extends AbstractTestUI { + public static final String SUCCESS_CAPTION = "Success!"; + public static final String BUTTON_ID = "blinkbutton"; + public static final String FAILURE_CAPTION = "Test failed"; + + private class WrappedConnectorTracker extends ConnectorTracker { + private ConnectorTracker tracker; + + private boolean initialDirtyHasBeenCalled = false; + + public WrappedConnectorTracker(ConnectorTracker tracker) { + super(TableRemovedQuicklySendsInvalidRpcCalls.this); + this.tracker = tracker; + } + + @Override + public void markAllConnectorsDirty() { + tracker.markAllConnectorsDirty(); + if (initialDirtyHasBeenCalled) { + button.setCaption(FAILURE_CAPTION); + } + initialDirtyHasBeenCalled = true; + } + + // DELEGATED METHODS BELOW: + + @Override + public void registerConnector(ClientConnector connector) { + tracker.registerConnector(connector); + } + + @Override + public void unregisterConnector(ClientConnector connector) { + tracker.unregisterConnector(connector); + } + + @Override + public boolean isClientSideInitialized(ClientConnector connector) { + return tracker.isClientSideInitialized(connector); + } + + @Override + public void markClientSideInitialized(ClientConnector connector) { + tracker.markClientSideInitialized(connector); + } + + @Override + public void markAllClientSidesUninitialized() { + tracker.markAllClientSidesUninitialized(); + } + + @Override + public ClientConnector getConnector(String connectorId) { + return tracker.getConnector(connectorId); + } + + @Override + public void cleanConnectorMap() { + tracker.cleanConnectorMap(); + } + + @Override + public void markDirty(ClientConnector connector) { + tracker.markDirty(connector); + } + + @Override + public void markClean(ClientConnector connector) { + tracker.markClean(connector); + } + + @Override + public void markAllConnectorsClean() { + tracker.markAllConnectorsClean(); + } + + @Override + public Collection<ClientConnector> getDirtyConnectors() { + return tracker.getDirtyConnectors(); + } + + @Override + public boolean hasDirtyConnectors() { + return tracker.hasDirtyConnectors(); + } + + @Override + public ArrayList<ClientConnector> getDirtyVisibleConnectors() { + return tracker.getDirtyVisibleConnectors(); + } + + @Override + public JSONObject getDiffState(ClientConnector connector) { + return tracker.getDiffState(connector); + } + + @Override + public void setDiffState(ClientConnector connector, JSONObject diffState) { + tracker.setDiffState(connector, diffState); + } + + @Override + public boolean isDirty(ClientConnector connector) { + return tracker.isDirty(connector); + } + + @Override + public boolean isWritingResponse() { + return tracker.isWritingResponse(); + } + + @Override + public void setWritingResponse(boolean writingResponse) { + tracker.setWritingResponse(writingResponse); + } + + @Override + public StreamVariable getStreamVariable(String connectorId, + String variableName) { + return tracker.getStreamVariable(connectorId, variableName); + } + + @Override + public void addStreamVariable(String connectorId, String variableName, + StreamVariable variable) { + tracker.addStreamVariable(connectorId, variableName, variable); + } + + @Override + public void cleanStreamVariable(String connectorId, String variableName) { + tracker.cleanStreamVariable(connectorId, variableName); + } + + @Override + public String getSeckey(StreamVariable variable) { + return tracker.getSeckey(variable); + } + + @Override + public boolean connectorWasPresentAsRequestWasSent(String connectorId, + long lastSyncIdSeenByClient) { + return tracker.connectorWasPresentAsRequestWasSent(connectorId, + lastSyncIdSeenByClient); + } + + @Override + public int getCurrentSyncId() { + return tracker.getCurrentSyncId(); + } + + @Override + public void cleanConcurrentlyRemovedConnectorIds( + int lastSyncIdSeenByClient) { + tracker.cleanConcurrentlyRemovedConnectorIds(lastSyncIdSeenByClient); + } + + @Override + public boolean equals(Object obj) { + return tracker.equals(obj); + } + + @Override + public int hashCode() { + return tracker.hashCode(); + } + + @Override + public String toString() { + return tracker.toString(); + } + } + + private Button button; + private WrappedConnectorTracker wrappedTracker = null; + @Override protected void setup(VaadinRequest request) { - addComponent(new Button("Blink a table", new Button.ClickListener() { + button = new Button("Blink a table", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { blinkTable(); } - })); + }); + button.setId(BUTTON_ID); + addComponent(button); + } + + @Override + public ConnectorTracker getConnectorTracker() { + if (wrappedTracker == null) { + wrappedTracker = new WrappedConnectorTracker( + super.getConnectorTracker()); + } + return wrappedTracker; } private void blinkTable() { @@ -47,25 +238,6 @@ public class TableRemovedQuicklySendsInvalidRpcCalls extends AbstractTestUI { table.addItem(new Object[] { "Row" }, new Object()); } - table.addItemClickListener(new ItemClickListener() { - private int i; - - @Override - public void itemClick(ItemClickEvent event) { - /* - * Ignore implementation. This is only an easy way to make the - * client-side update table's variables (by furiously clicking - * on the table row. - * - * This way, we get variable changes queued. The push call will - * then remove the Table, while the variable changes being still - * in the queue, leading to the issue as described in the - * ticket. - */ - System.out.println("clicky " + (++i)); - } - }); - System.out.println("adding component"); addComponent(table); @@ -80,6 +252,7 @@ public class TableRemovedQuicklySendsInvalidRpcCalls extends AbstractTestUI { public void run() { System.out.println("removing component"); removeComponent(table); + button.setCaption(SUCCESS_CAPTION); } }); } catch (InterruptedException e) { @@ -87,7 +260,7 @@ public class TableRemovedQuicklySendsInvalidRpcCalls extends AbstractTestUI { } finally { getSession().unlock(); } - }; + } }.start(); } @@ -96,8 +269,9 @@ public class TableRemovedQuicklySendsInvalidRpcCalls extends AbstractTestUI { return "Adding and subsequently quickly removing a table " + "should not leave any pending RPC calls waiting " + "in a Timer. Issue can be reproduced by " - + "1) pressing the button 2) clicking furiously " - + "on a row in the table."; + + "1) pressing the button 2) checking the server " + + "log for any error messages starting with " + + "\"RPC call to...\" ."; } @Override diff --git a/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCallsTest.java b/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCallsTest.java new file mode 100644 index 0000000000..68c8dc9884 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableRemovedQuicklySendsInvalidRpcCallsTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.table; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class TableRemovedQuicklySendsInvalidRpcCallsTest extends + MultiBrowserTest { + + private static final String BUTTON_ID = TableRemovedQuicklySendsInvalidRpcCalls.BUTTON_ID; + private static final String FAILURE_CAPTION = TableRemovedQuicklySendsInvalidRpcCalls.FAILURE_CAPTION; + private static final String SUCCESS_CAPTION = TableRemovedQuicklySendsInvalidRpcCalls.SUCCESS_CAPTION; + + @Test + public void test() throws Exception { + setDebug(true); + openTestURL(); + + assertFalse("Test started with the error present.", button().getText() + .equals(FAILURE_CAPTION)); + assertFalse("Test jumped the gun.", + button().getText().equals(SUCCESS_CAPTION)); + + button().click(); + Thread.sleep(5000); + + assertFalse("Test failed after trying to trigger the error.", button() + .getText().equals(FAILURE_CAPTION)); + assertTrue("Test didn't end up in correct success state.", button() + .getText().equals(SUCCESS_CAPTION)); + } + + private WebElement button() { + return vaadinElementById(BUTTON_ID); + } +} diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetFocusedTabTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetFocusedTabTest.java new file mode 100644 index 0000000000..81648c1b52 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetFocusedTabTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.tabsheet; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.testbench.By; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class TabSheetFocusedTabTest extends MultiBrowserTest { + + @Override + protected Class<?> getUIClass() { + return TabsheetScrolling.class; + } + + @Test + public void clickingChangesFocusedTab() throws Exception { + openTestURL(); + + getTab(1).click(); + + assertTrue(isFocused(getTab(1))); + + new Actions(getDriver()).sendKeys(Keys.RIGHT).perform(); + + assertFalse(isFocused(getTab(1))); + assertTrue(isFocused(getTab(3))); + + getTab(5).click(); + + assertFalse(isFocused(getTab(3))); + assertTrue(isFocused(getTab(5))); + + getTab(1).click(); + + assertFalse(isFocused(getTab(5))); + assertTrue(isFocused(getTab(1))); + } + + private WebElement getTab(int index) { + return getDriver() + .findElement( + By.xpath("(//table[contains(@class, 'v-tabsheet-tabs')])[1]/tbody/tr/td[" + + (index + 1) + "]/div")); + } + + private boolean isFocused(WebElement tab) { + return tab.getAttribute("class").contains("v-tabsheet-tabitem-focus"); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetScrollingTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetScrollingTest.java new file mode 100644 index 0000000000..b55f1057b5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetScrollingTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.tabsheet; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.testbench.By; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class TabsheetScrollingTest extends MultiBrowserTest { + + @Test + public void keyboardScrolling() { + openTestURL(); + getTab(1).click(); + for (int i = 0; i < 10; i++) { + sendKey(Keys.ARROW_RIGHT); + } + sendKey(Keys.SPACE); + Assert.assertEquals("Hide this tab (21)", getHideButtonText()); + } + + private WebElement getTab(int index) { + return getDriver().findElement( + By.vaadin("/VVerticalLayout[0]/Slot[1]" + + "/VVerticalLayout[0]/Slot[0]/VTabsheet[0]" + + "/domChild[0]/domChild[0]/domChild[0]" + + "/domChild[0]/domChild[" + index + "]")); + + } + + private String getHideButtonText() { + WebElement buttonCaption = getDriver().findElement( + By.vaadin("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]" + + "/Slot[0]/VTabsheet[0]/VTabsheetPanel[0]" + + "/VButton[0]/domChild[0]/domChild[0]")); + return buttonCaption.getText(); + } + + private void sendKey(Keys key) { + new Actions(getDriver()).sendKeys(key).perform(); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/textfield/AutomaticImmediate.java b/uitest/src/com/vaadin/tests/components/textfield/AutomaticImmediate.java new file mode 100644 index 0000000000..26716846fc --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textfield/AutomaticImmediate.java @@ -0,0 +1,147 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.textfield; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.TextField; + +/** + * Test to verify fields become implicitly "immediate" when adding value change + * listener to them. + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class AutomaticImmediate extends AbstractTestUIWithLog { + + /** + * + */ + static final String BUTTON = "button"; + /** + * + */ + static final String EXPLICIT_FALSE = "explicit-false"; + /** + * + */ + static final String FIELD = "field"; + /** + * + */ + static final String LISTENER_TOGGLE = "listener-toggle"; + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server. + * VaadinRequest) + */ + @Override + protected void setup(VaadinRequest request) { + + final TextField textField = new TextField() { + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.AbstractField#fireValueChange(boolean) + */ + @Override + protected void fireValueChange(boolean repaintIsNotNeeded) { + log("fireValueChange"); + super.fireValueChange(repaintIsNotNeeded); + } + }; + textField.setId(FIELD); + + final ValueChangeListener listener = new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + log("Value changed: " + event.getProperty().getValue()); + } + }; + + final CheckBox checkBox = new CheckBox("Toggle listener"); + checkBox.addValueChangeListener(new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + if (checkBox.getValue()) { + textField.addValueChangeListener(listener); + } else { + textField.removeValueChangeListener(listener); + } + } + }); + checkBox.setId(LISTENER_TOGGLE); + + Button b = new Button( + "setImmediate(false), sets explicitly false and causes server roundtrip", + new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + textField.setImmediate(false); + } + }); + b.setId(EXPLICIT_FALSE); + + Button b2 = new Button("Hit server, causes server roundtrip", + new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + } + }); + b2.setId(BUTTON); + + addComponent(textField); + addComponent(checkBox); + addComponent(b); + addComponent(b2); + + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription() + */ + @Override + protected String getTestDescription() { + return "Field should be immediate automatically if it has value change listener"; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber() + */ + @Override + protected Integer getTicketNumber() { + return 8029; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/textfield/AutomaticImmediateTest.java b/uitest/src/com/vaadin/tests/components/textfield/AutomaticImmediateTest.java new file mode 100644 index 0000000000..4b522a1f37 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textfield/AutomaticImmediateTest.java @@ -0,0 +1,109 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.textfield; + +import org.apache.commons.lang.RandomStringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class AutomaticImmediateTest extends MultiBrowserTest { + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.tb3.AbstractTB3Test#getUIClass() + */ + @Override + protected Class<?> getUIClass() { + return AutomaticImmediate.class; + } + + @Test + public void test() { + openTestURL(); + + WebElement field = getDriver().findElement( + By.id(AutomaticImmediate.FIELD)); + + WebElement toggle = getDriver().findElement( + By.xpath("//input[@type = 'checkbox']")); + + WebElement explicitFalseButton = getDriver().findElement( + By.id(AutomaticImmediate.EXPLICIT_FALSE)); + + WebElement hitServerButton = getDriver().findElement( + By.id(AutomaticImmediate.BUTTON)); + + String string = getRandomString(); + field.sendKeys(string + Keys.ENTER); + + // Non immediate, just the initial server side valuechange + assertLastLog("1. fireValueChange"); + + hitServerButton.click(); + + // No value change, but value sent to server + assertLastLog("2. fireValueChange"); + + // listener on -> immediate on + toggle.click(); + + string = getRandomString(); + String delSequence = "" + Keys.BACK_SPACE + Keys.BACK_SPACE; + field.sendKeys(delSequence + string + Keys.ENTER); + assertLastLog("4. Value changed: " + string); + + // listener off -> immediate off + String lastvalue = string; + toggle.click(); + string = getRandomString(); + field.sendKeys(delSequence + string + Keys.ENTER); + // No new value change should happen... + assertLastLog("4. Value changed: " + lastvalue); + hitServerButton.click(); + // ... but server should receive value with roundtrip + assertLastLog("5. fireValueChange"); + + // explicitly non immediate, but with listener + explicitFalseButton.click(); + toggle.click(); + + string = getRandomString(); + field.sendKeys(delSequence + string + Keys.ENTER); + // non immediate, no change... + assertLastLog("5. fireValueChange"); + // ... until server round trip + hitServerButton.click(); + assertLastLog("7. Value changed: " + string); + + } + + private String getRandomString() { + String string = RandomStringUtils.randomAlphanumeric(2); + return string; + } + + private void assertLastLog(String string) { + String text = getDriver().findElement(By.id("Log_row_0")).getText(); + Assert.assertEquals(string, text); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/textfield/TextFieldTruncatesUnderscoresInModalDialogs.java b/uitest/src/com/vaadin/tests/components/textfield/TextFieldTruncatesUnderscoresInModalDialogs.java new file mode 100644 index 0000000000..2a9df42ba1 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textfield/TextFieldTruncatesUnderscoresInModalDialogs.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.textfield; + +import com.vaadin.annotations.Theme; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.TextField; +import com.vaadin.ui.Window; + +@SuppressWarnings("serial") +@Theme("chameleon") +public class TextFieldTruncatesUnderscoresInModalDialogs extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + final Window dialog = new Window(); + + FormLayout formLayout = new FormLayout(); + formLayout.setSpacing(true); + + formLayout.addComponent(new Button("Disappear", + new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + event.getButton().setVisible(false); + } + })); + + formLayout.addComponent(new TextField(null, "____pqjgy____")); + + dialog.setContent(formLayout); + + getUI().addWindow(dialog); + } + + @Override + protected String getTestDescription() { + return "Text field must not truncate underscores in modal dialogs."; + } + + @Override + protected Integer getTicketNumber() { + return 12974; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/textfield/TextFieldTruncatesUnderscoresInModalDialogsTest.java b/uitest/src/com/vaadin/tests/components/textfield/TextFieldTruncatesUnderscoresInModalDialogsTest.java new file mode 100644 index 0000000000..66b0df5ff4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/textfield/TextFieldTruncatesUnderscoresInModalDialogsTest.java @@ -0,0 +1,16 @@ +package com.vaadin.tests.components.textfield; + +import org.junit.Test; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class TextFieldTruncatesUnderscoresInModalDialogsTest extends + MultiBrowserTest { + + @Test + public void testWindowRepositioning() throws Exception { + openTestURL(); + + compareScreen("TextFieldTruncatesUnderscoresInModalDialogs"); + } +} diff --git a/uitest/src/com/vaadin/tests/components/tree/TreeScrollingOnRightClick.java b/uitest/src/com/vaadin/tests/components/tree/TreeScrollingOnRightClick.java new file mode 100644 index 0000000000..8a2b263006 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tree/TreeScrollingOnRightClick.java @@ -0,0 +1,53 @@ +package com.vaadin.tests.components.tree; + +import com.vaadin.event.ItemClickEvent; +import com.vaadin.event.MouseEvents; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Tree; + +/** + * Test for #12618: Trying to select item with right click in Tree causes focus + * issues. + */ +@SuppressWarnings("serial") +public class TreeScrollingOnRightClick extends AbstractTestUI { + + public static final String TREE_ID = "my-tree"; + + @Override + protected void setup(VaadinRequest request) { + final Tree tree = new Tree(); + tree.setId(TREE_ID); + tree.setSizeUndefined(); + + // Add item click listener for right click selection + tree.addItemClickListener(new ItemClickEvent.ItemClickListener() { + @SuppressWarnings("deprecation") + @Override + public void itemClick(ItemClickEvent event) { + if (event.getButton() == MouseEvents.ClickEvent.BUTTON_RIGHT) { + tree.select(event.getItemId()); + } + } + }); + + // Add some items + for (int i = 0; i < 200; i++) { + tree.addItem(String.format("Node %s", i)); + } + + addComponent(tree); + } + + @Override + protected String getTestDescription() { + return "Right clicking on items should not scroll Tree."; + } + + @Override + protected Integer getTicketNumber() { + return 12618; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/tree/TreeScrollingOnRightClickTest.java b/uitest/src/com/vaadin/tests/components/tree/TreeScrollingOnRightClickTest.java new file mode 100644 index 0000000000..76ab1b3fdb --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tree/TreeScrollingOnRightClickTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.tree; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.Point; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * + * @since 7.1.9 + * @author Vaadin Ltd + */ +public class TreeScrollingOnRightClickTest extends MultiBrowserTest { + + @Test + public void testScrollingOnRightClick() throws Throwable { + openTestURL(); + + // Focus tree + WebElement tree = getDriver().findElement( + By.id(TreeScrollingOnRightClick.TREE_ID)); + tree.click(); + + // Move selection down 50 items + for (int down = 0; down < 50; down++) { + tree.sendKeys(Keys.ARROW_DOWN); + } + + Thread.sleep(1000); + + // Get location of item 40 + Point item40Location = getTreeNode("Node 40").getLocation(); + + // Right click on item 45 + WebElement item45 = getTreeNode("Node 45"); + new Actions(getDriver()).moveToElement(item45).contextClick(item45) + .perform(); + + // Ensure location of item 40 is still the same (no scrolling) + Point item40Location2 = getTreeNode("Node 40").getLocation(); + assertEquals(item40Location.getY(), item40Location2.getY()); + } + + private WebElement getTreeNode(String caption) { + return getDriver().findElement( + By.xpath("//span[text() = '" + caption + "']")); + } +} diff --git a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset.java b/uitest/src/com/vaadin/tests/components/ui/ComponentIncludedInCustomWidgetset.java index e837321b56..f674567a2d 100644 --- a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset.java +++ b/uitest/src/com/vaadin/tests/components/ui/ComponentIncludedInCustomWidgetset.java @@ -6,11 +6,13 @@ import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent; @Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet") -public class TestUIWidgetset extends AbstractTestUI { +public class ComponentIncludedInCustomWidgetset extends AbstractTestUI { @Override protected void setup(VaadinRequest request) { - addComponent(new MissingFromDefaultWidgetsetComponent()); + MissingFromDefaultWidgetsetComponent component = new MissingFromDefaultWidgetsetComponent(); + component.setId("missing-component"); + addComponent(component); } @Override diff --git a/uitest/src/com/vaadin/tests/components/ui/ComponentIncludedInCustomWidgetsetTest.java b/uitest/src/com/vaadin/tests/components/ui/ComponentIncludedInCustomWidgetsetTest.java new file mode 100644 index 0000000000..f27ef5d789 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/ComponentIncludedInCustomWidgetsetTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.ui; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests if a component is included in a custom widgetset + * (com.vaadin.tests.widgetset.TestingWidgetSet) + * + * @author Vaadin Ltd + */ +public class ComponentIncludedInCustomWidgetsetTest extends MultiBrowserTest { + + @Test + public void testComponentInTestingWidgetsetNotInDefaultWidgetset() { + openTestURL(); + WebElement component = vaadinElementById("missing-component"); + assertEquals( + "This component is available in TestingWidgetset, but not in DefaultWidgetset", + component.getText()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset2.java b/uitest/src/com/vaadin/tests/components/ui/ComponentMissingFromDefaultWidgetset.java index a68cd91a5e..554a461c37 100644 --- a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset2.java +++ b/uitest/src/com/vaadin/tests/components/ui/ComponentMissingFromDefaultWidgetset.java @@ -4,11 +4,13 @@ import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent; -public class TestUIWidgetset2 extends AbstractTestUI { +public class ComponentMissingFromDefaultWidgetset extends AbstractTestUI { @Override protected void setup(VaadinRequest request) { - addComponent(new MissingFromDefaultWidgetsetComponent()); + MissingFromDefaultWidgetsetComponent component = new MissingFromDefaultWidgetsetComponent(); + component.setId("missing-component"); + addComponent(component); } @Override diff --git a/uitest/src/com/vaadin/tests/components/ui/ComponentMissingFromDefaultWidgetsetTest.java b/uitest/src/com/vaadin/tests/components/ui/ComponentMissingFromDefaultWidgetsetTest.java new file mode 100644 index 0000000000..ec8add75e0 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/ComponentMissingFromDefaultWidgetsetTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.ui; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test for testing if a component is missing from a widgetset. + * + * @author Vaadin Ltd + */ +public class ComponentMissingFromDefaultWidgetsetTest extends MultiBrowserTest { + + @Test + public void testComponentInTestingWidgetset() { + openTestURL(); + WebElement component = vaadinElementById("missing-component"); + assertTrue(component + .getText() + .startsWith( + "Widgetset 'com.vaadin.DefaultWidgetSet' does not contain implementation for com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent.")); + + } +} diff --git a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset.html b/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset.html deleted file mode 100644 index 4c10dc4275..0000000000 --- a/uitest/src/com/vaadin/tests/components/ui/TestUIWidgetset.html +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> -<title>Ticket4607</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">Ticket4607</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.ui.TestUIWidgetset?restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentsuiTestUIWidgetset::/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[0]</td> - <td>This component is available in TestingWidgetset, but not in DefaultWidgetset</td> -</tr> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.ui.TestUIWidgetset2?restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentsuiTestUIWidgetset2::/VVerticalLayout[0]/VVerticalLayout[0]/VUnknownComponent[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> - <td>Widgetset does not contain implementation for com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent. Check its component connector's @Connect mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions.</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/ui/TimeoutRedirectResetsOnActivity.java b/uitest/src/com/vaadin/tests/components/ui/TimeoutRedirectResetsOnActivity.java new file mode 100644 index 0000000000..2c649c9ca8 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/TimeoutRedirectResetsOnActivity.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.ui; + +import com.vaadin.server.CustomizedSystemMessages; +import com.vaadin.server.SystemMessages; +import com.vaadin.server.SystemMessagesInfo; +import com.vaadin.server.SystemMessagesProvider; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; + +public class TimeoutRedirectResetsOnActivity extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + setupTimout(request); + + addComponent(new Button("clicky", new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + // NOOP + } + })); + } + + private void setupTimout(VaadinRequest request) { + request.getService().setSystemMessagesProvider( + new SystemMessagesProvider() { + @Override + public SystemMessages getSystemMessages( + SystemMessagesInfo systemMessagesInfo) { + CustomizedSystemMessages msgs = new CustomizedSystemMessages(); + msgs.setSessionExpiredMessage(null); + msgs.setSessionExpiredCaption(null); + msgs.setSessionExpiredNotificationEnabled(true); + msgs.setSessionExpiredURL("http://example.com/"); + return msgs; + } + }); + /* + * NOTE: in practice, this means a timeout after 25 seconds, because of + * implementation details in + * com.vaadin.server.communication.MetadataWriter + */ + getSession().getSession().setMaxInactiveInterval(10); + } + + @Override + protected String getTestDescription() { + return "The timeout redirect timer should reset if there's activity between the client and server."; + } + + @Override + @SuppressWarnings("boxing") + protected Integer getTicketNumber() { + return 12446; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/ui/TimeoutRedirectResetsOnActivityTest.java b/uitest/src/com/vaadin/tests/components/ui/TimeoutRedirectResetsOnActivityTest.java new file mode 100644 index 0000000000..272bacb8d5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/TimeoutRedirectResetsOnActivityTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.ui; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class TimeoutRedirectResetsOnActivityTest extends MultiBrowserTest { + @Test + public void verifyRedirectWorks() throws Exception { + setDebug(true); + openTestURL(); + + long startTime = System.currentTimeMillis(); + while (System.currentTimeMillis() - startTime < 30000) { + clickTheButton(); + Thread.sleep(1000); + } + + assertTrue("button disappeared before timeout", buttonIsStillThere()); + + Thread.sleep(30000); + assertTrue("no redirection occurred within 30 seconds", + !buttonIsStillThere()); + } + + private boolean buttonIsStillThere() { + try { + return getButton() != null; + } catch (NoSuchElementException e) { + return false; + } + } + + private void clickTheButton() { + getButton().click(); + } + + private WebElement getButton() { + /* + * For some reason, the vaadinElement() method doesn't work when tests + * are run outside of "/run/" and "/run-push/" contexts. The given error + * message says that the generated Vaadin path doesn't match any + * elements, but when that selector is put into the recorder, the + * recorder finds it. + * + * XPath works fine. + */ + /*- + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]"); + */ + return getDriver().findElement( + By.xpath("//div[contains(@class,'v-button')]")); + } + + @Override + protected String getDeploymentPath() { + /* + * AbstractTB3Test assumes only /run/ and /run-push/ contexts, so this + * method needs some overriding. + */ + return "/12446/" + + TimeoutRedirectResetsOnActivity.class.getCanonicalName() + + "?restartApplication&debug"; + } +} diff --git a/uitest/src/com/vaadin/tests/components/ui/UIAccess.java b/uitest/src/com/vaadin/tests/components/ui/UIAccess.java deleted file mode 100644 index d036827159..0000000000 --- a/uitest/src/com/vaadin/tests/components/ui/UIAccess.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright 2000-2013 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 com.vaadin.tests.components.ui; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.locks.ReentrantLock; - -import com.vaadin.server.VaadinRequest; -import com.vaadin.server.VaadinService; -import com.vaadin.server.VaadinSession; -import com.vaadin.shared.communication.PushMode; -import com.vaadin.tests.components.AbstractTestUIWithLog; -import com.vaadin.ui.Button; -import com.vaadin.ui.Button.ClickEvent; -import com.vaadin.ui.UI; -import com.vaadin.util.CurrentInstance; - -public class UIAccess extends AbstractTestUIWithLog { - - private volatile boolean checkCurrentInstancesBeforeResponse = false; - - private Future<Void> checkFromBeforeClientResponse; - - private class CurrentInstanceTestType { - private String value; - - public CurrentInstanceTestType(String value) { - this.value = value; - } - - @Override - public String toString() { - return value; - } - } - - @Override - protected void setup(VaadinRequest request) { - addComponent(new Button("Access from UI thread", - new Button.ClickListener() { - - @Override - public void buttonClick(ClickEvent event) { - log.clear(); - // Ensure beforeClientResponse is invoked - markAsDirty(); - checkFromBeforeClientResponse = access(new Runnable() { - @Override - public void run() { - log("Access from UI thread is run"); - } - }); - log("Access from UI thread future is done? " - + checkFromBeforeClientResponse.isDone()); - } - })); - addComponent(new Button("Access from background thread", - new Button.ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - log.clear(); - final CountDownLatch latch = new CountDownLatch(1); - - new Thread() { - @Override - public void run() { - final boolean threadHasCurrentResponse = VaadinService - .getCurrentResponse() != null; - // session is locked by request thread at this - // point - final Future<Void> initialFuture = access(new Runnable() { - @Override - public void run() { - log("Initial background message"); - log("Thread has current response? " - + threadHasCurrentResponse); - } - }); - - // Let request thread continue - latch.countDown(); - - // Wait until thread can be locked - while (!getSession().getLockInstance() - .tryLock()) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - try { - log("Thread got lock, inital future done? " - + initialFuture.isDone()); - setPollInterval(-1); - } finally { - getSession().unlock(); - } - } - }.start(); - - // Wait for thread to do initialize before continuing - try { - latch.await(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - setPollInterval(3000); - } - })); - addComponent(new Button("Access throwing exception", - new Button.ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - log.clear(); - final Future<Void> firstFuture = access(new Runnable() { - @Override - public void run() { - log("Throwing exception in access"); - throw new RuntimeException( - "Catch me if you can"); - } - }); - access(new Runnable() { - @Override - public void run() { - log("firstFuture is done? " - + firstFuture.isDone()); - try { - firstFuture.get(); - log("Should not get here"); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } catch (ExecutionException e) { - log("Got exception from firstFuture: " - + e.getMessage()); - } - } - }); - } - })); - addComponent(new Button("Cancel future before started", - new Button.ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - log.clear(); - Future<Void> future = access(new Runnable() { - @Override - public void run() { - log("Should not get here"); - } - }); - future.cancel(false); - log("future was cancled, should not start"); - } - })); - addComponent(new Button("Cancel running future", - new Button.ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - log.clear(); - final ReentrantLock interruptLock = new ReentrantLock(); - - final Future<Void> future = access(new Runnable() { - @Override - public void run() { - log("Waiting for thread to start"); - while (!interruptLock.isLocked()) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - log("Premature interruption"); - throw new RuntimeException(e); - } - } - - log("Thread started, waiting for interruption"); - try { - interruptLock.lockInterruptibly(); - } catch (InterruptedException e) { - log("I was interrupted"); - } - } - }); - - new Thread() { - @Override - public void run() { - interruptLock.lock(); - // Wait until UI thread has started waiting for - // the lock - while (!interruptLock.hasQueuedThreads()) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - future.cancel(true); - } - }.start(); - } - })); - addComponent(new Button("CurrentInstance accessSynchronously values", - new Button.ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - log.clear(); - // accessSynchronously should maintain values - CurrentInstance.set(CurrentInstanceTestType.class, - new CurrentInstanceTestType( - "Set before accessSynchronosly")); - accessSynchronously(new Runnable() { - @Override - public void run() { - log.log("accessSynchronously has request? " - + (VaadinService.getCurrentRequest() != null)); - log.log("Test value in accessSynchronously: " - + CurrentInstance - .get(CurrentInstanceTestType.class)); - CurrentInstance.set( - CurrentInstanceTestType.class, - new CurrentInstanceTestType( - "Set in accessSynchronosly")); - } - }); - log.log("has request after accessSynchronously? " - + (VaadinService.getCurrentRequest() != null)); - log("Test value after accessSynchornously: " - + CurrentInstance - .get(CurrentInstanceTestType.class)); - } - })); - addComponent(new Button("CurrentInstance access values", - new Button.ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - log.clear(); - // accessSynchronously should maintain values - CurrentInstance - .setInheritable(CurrentInstanceTestType.class, - new CurrentInstanceTestType( - "Set before access")); - access(new Runnable() { - @Override - public void run() { - log.log("access has request? " - + (VaadinService.getCurrentRequest() != null)); - log.log("Test value in access: " - + CurrentInstance - .get(CurrentInstanceTestType.class)); - CurrentInstance.setInheritable( - CurrentInstanceTestType.class, - new CurrentInstanceTestType( - "Set in access")); - } - }); - CurrentInstance.setInheritable( - CurrentInstanceTestType.class, - new CurrentInstanceTestType( - "Set before run pending")); - - getSession().getService().runPendingAccessTasks( - getSession()); - - log.log("has request after access? " - + (VaadinService.getCurrentRequest() != null)); - log("Test value after access: " - + CurrentInstance - .get(CurrentInstanceTestType.class)); - } - })); - - addComponent(new Button("CurrentInstance when pushing", - new Button.ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - log.clear(); - if (getPushConfiguration().getPushMode() != PushMode.AUTOMATIC) { - log("Can only test with automatic push enabled"); - return; - } - - final VaadinSession session = getSession(); - new Thread() { - @Override - public void run() { - // Pretend this isn't a Vaadin thread - CurrentInstance.clearAll(); - - /* - * Get explicit lock to ensure the (implicit) - * push does not happen during normal request - * handling. - */ - session.lock(); - try { - access(new Runnable() { - @Override - public void run() { - checkCurrentInstancesBeforeResponse = true; - // Trigger beforeClientResponse - markAsDirty(); - } - }); - } finally { - session.unlock(); - } - } - }.start(); - } - })); - } - - @Override - public void beforeClientResponse(boolean initial) { - if (checkFromBeforeClientResponse != null) { - log("beforeClientResponse future is done? " - + checkFromBeforeClientResponse.isDone()); - checkFromBeforeClientResponse = null; - } - if (checkCurrentInstancesBeforeResponse) { - UI currentUI = UI.getCurrent(); - VaadinSession currentSession = VaadinSession.getCurrent(); - - log("Current UI matches in beforeResponse? " + (currentUI == this)); - log("Current session matches in beforeResponse? " - + (currentSession == getSession())); - checkCurrentInstancesBeforeResponse = false; - } - } - - @Override - protected String getTestDescription() { - return "Test for various ways of using UI.access"; - } - - @Override - protected Integer getTicketNumber() { - return Integer.valueOf(11897); - } - -} diff --git a/uitest/src/com/vaadin/tests/components/upload/UploadNoSelection.java b/uitest/src/com/vaadin/tests/components/upload/UploadNoSelection.java new file mode 100644 index 0000000000..c304293170 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/upload/UploadNoSelection.java @@ -0,0 +1,83 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.upload; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.Upload; +import com.vaadin.ui.Upload.FailedEvent; +import com.vaadin.ui.Upload.FinishedEvent; +import com.vaadin.ui.Upload.Receiver; + +public class UploadNoSelection extends AbstractTestUIWithLog implements + Receiver { + + static final String LOG_ID_PREFIX = "Log_row_"; + static final String UPLOAD_ID = "u"; + + static final String UPLOAD_FINISHED = "Upload Finished"; + static final String RECEIVING_UPLOAD = "Receiving upload"; + + static final String FILE_LENGTH_PREFIX = "File length:"; + static final String FILE_NAME_PREFIX = "File name:"; + + @Override + protected Integer getTicketNumber() { + return 9602; + } + + @Override + protected String getTestDescription() { + return "Uploading an empty selection (no file) will trigger FinishedEvent with 0-length file size and empty filename."; + } + + @Override + protected void setup(VaadinRequest request) { + Upload u = new Upload("Upload", this); + u.setId(UPLOAD_ID); + u.setSizeUndefined(); + + addComponent(u); + + u.addFinishedListener(new Upload.FinishedListener() { + @Override + public void uploadFinished(FinishedEvent event) { + log(UPLOAD_FINISHED); + log(FILE_LENGTH_PREFIX + " " + event.getLength()); + log(FILE_NAME_PREFIX + " " + event.getFilename()); + } + }); + u.addFailedListener(new Upload.FailedListener() { + + @Override + public void uploadFailed(FailedEvent event) { + log("Upload Failed"); + log(FILE_LENGTH_PREFIX + " " + event.getLength()); + log(FILE_NAME_PREFIX + " " + event.getFilename()); + } + }); + } + + @Override + public OutputStream receiveUpload(String filename, String MIMEType) { + log(RECEIVING_UPLOAD); + return new ByteArrayOutputStream(); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/upload/UploadNoSelectionTest.java b/uitest/src/com/vaadin/tests/components/upload/UploadNoSelectionTest.java new file mode 100644 index 0000000000..1b30c4080a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/upload/UploadNoSelectionTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.upload; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class UploadNoSelectionTest extends MultiBrowserTest { + + @Test + public void testUploadNoSelection() throws Exception { + openTestURL(); + + // empty content is populated by com.vaadin.tests.util.Log + Assert.assertEquals(" ", getLogRow(0)); + + getSubmitButton().click(); + + // expecting empty file name + assertLogRow(0, 4, UploadNoSelection.FILE_NAME_PREFIX); + // expecting 0-length file + assertLogRow(1, 3, UploadNoSelection.FILE_LENGTH_PREFIX + " " + 0); + assertLogRow(2, 2, UploadNoSelection.UPLOAD_FINISHED); + assertLogRow(3, 1, UploadNoSelection.RECEIVING_UPLOAD); + } + + private WebElement getSubmitButton() { + WebElement element = getDriver().findElement( + By.id(UploadNoSelection.UPLOAD_ID)); + WebElement submitButton = element.findElement(By.className("v-button")); + return submitButton; + } + + private void assertLogRow(int index, int expentedRowNo, + String expectedValueWithoutRowNo) { + Assert.assertEquals(expentedRowNo + ". " + expectedValueWithoutRowNo, + getLogRow(index)); + } +} diff --git a/uitest/src/com/vaadin/tests/components/window/ScrollingBodyElementWithModalOpened.java b/uitest/src/com/vaadin/tests/components/window/ScrollingBodyElementWithModalOpened.java new file mode 100644 index 0000000000..2f1c0ff685 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/window/ScrollingBodyElementWithModalOpened.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.window; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +/** + * + * @since 7.1.9 + * @author Vaadin Ltd + */ +public class ScrollingBodyElementWithModalOpened extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + VerticalLayout verticalLayout = new VerticalLayout(); + verticalLayout.setHeight("10000px"); + + Window window = new Window("Caption"); + + VerticalLayout layout = new VerticalLayout(); + layout.setWidth("300px"); + layout.setHeight("300px"); + window.setContent(layout); + + addWindow(window); + + window.setModal(true); + + addComponent(verticalLayout); + } + + @Override + protected String getTestDescription() { + return "Screen must not scroll with modal opened."; + } + + @Override + protected Integer getTicketNumber() { + return 12899; + } +} diff --git a/uitest/src/com/vaadin/tests/components/window/ScrollingBodyElementWithModalOpenedTest.java b/uitest/src/com/vaadin/tests/components/window/ScrollingBodyElementWithModalOpenedTest.java new file mode 100644 index 0000000000..b6474519b0 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/window/ScrollingBodyElementWithModalOpenedTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.window; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.commands.TestBenchElementCommands; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * + * @since + * @author Vaadin Ltd + */ +public class ScrollingBodyElementWithModalOpenedTest extends MultiBrowserTest { + + @Test + public void testWindowScrollbars() throws Exception { + openTestURL(); + + WebElement bodyElement = driver.findElement(By + .className("v-modal-window-open")); + + TestBenchElementCommands scrollable = testBenchElement(bodyElement); + scrollable.scroll(1000); + + Thread.sleep(1000); + + compareScreen(getScreenshotBaseName()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/window/SubWindowsTextSelectionTest.java b/uitest/src/com/vaadin/tests/components/window/SubWindowsTextSelectionTest.java index 1df036af58..2e0873956c 100644 --- a/uitest/src/com/vaadin/tests/components/window/SubWindowsTextSelectionTest.java +++ b/uitest/src/com/vaadin/tests/components/window/SubWindowsTextSelectionTest.java @@ -15,7 +15,6 @@ */ package com.vaadin.tests.components.window; -import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; @@ -64,7 +63,7 @@ public class SubWindowsTextSelectionTest extends MultiBrowserTest { } @Test - public void verifyNoTextSelectionOnMove() throws MalformedURLException { + public void verifyNoTextSelectionOnMove() throws Exception { openTestURL(); diff --git a/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.html b/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.html deleted file mode 100644 index 575eb652b7..0000000000 --- a/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.html +++ /dev/null @@ -1,86 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> -<title>TooltipInWindow</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">TooltipInWindow</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.window.TooltipInWindow?restartApplication</td> - <td></td> -</tr> -<!--Show tooltip in Root--> -<tr> - <td>showTooltip</td> - <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::/VVerticalLayout[0]/VVerticalLayout[0]/VTextField[0]</td> - <td>5,5</td> -</tr> -<tr> - <td>pause</td> - <td>1000</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td> - <td>My tooltip</td> -</tr> -<!--Hide the tooltip--> -<tr> - <td>showTooltip</td> - <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::/VVerticalLayout[0]</td> - <td>0,0</td> -</tr> -<tr> - <td>pause</td> - <td>1000</td> - <td></td> -</tr> -<tr> - <td>assertElementPositionLeft</td> - <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::Root/VTooltip[0]</td> - <td>-1000</td> -</tr> -<!--Show tooltip in Window--> -<tr> - <td>showTooltip</td> - <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VTextField[0]</td> - <td>5,5</td> -</tr> -<tr> - <td>pause</td> - <td>1000</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td> - <td>My tooltip</td> -</tr> -<!-- Hide tooltip in Window --> -<tr> - <td>showTooltip</td> - <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]</td> - <td>0,0</td> -</tr> -<tr> - <td>pause</td> - <td>1000</td> - <td></td> -</tr> -<tr> - <td>assertElementPositionLeft</td> - <td>vaadin=runcomvaadintestscomponentswindowTooltipInWindow::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td> - <td>-1000</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.java b/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.java index d3c7a616cd..02ec0c047b 100644 --- a/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.java +++ b/uitest/src/com/vaadin/tests/components/window/TooltipInWindow.java @@ -31,15 +31,16 @@ public class TooltipInWindow extends AbstractTestUI { Window window = new Window("Window", layout); layout.setSizeUndefined(); window.center(); - layout.addComponent(createTextField()); + layout.addComponent(createTextField("tf1")); addWindow(window); - addComponent(createTextField()); + addComponent(createTextField("tf2")); } - private TextField createTextField() { + private TextField createTextField(String id) { TextField tf = new TextField("TextField with a tooltip"); tf.setDescription("My tooltip"); + tf.setId(id); return tf; } diff --git a/uitest/src/com/vaadin/tests/components/window/TooltipInWindowTest.java b/uitest/src/com/vaadin/tests/components/window/TooltipInWindowTest.java new file mode 100644 index 0000000000..0e11041e3b --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/window/TooltipInWindowTest.java @@ -0,0 +1,98 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.components.window; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.HasInputDevices; +import org.openqa.selenium.interactions.Mouse; +import org.openqa.selenium.interactions.internal.Coordinates; +import org.openqa.selenium.internal.Locatable; + +import com.vaadin.testbench.By; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * + * @since + * @author Vaadin Ltd + */ +public class TooltipInWindowTest extends MultiBrowserTest { + + @Test + public void testTooltipsInSubWindow() throws Exception { + openTestURL(); + + WebElement textfield = vaadinElementById("tf1"); + Coordinates textfieldCoordinates = ((Locatable) textfield) + .getCoordinates(); + + Mouse mouse = ((HasInputDevices) getDriver()).getMouse(); + + // Show tooltip + mouse.mouseMove(textfieldCoordinates, 10, 10); + sleep(1000); + + ensureVisibleTooltipPositionedCorrectly(); + assertEquals("My tooltip", getTooltipElement().getText()); + + // Hide tooltip + mouse.mouseMove(textfieldCoordinates, -100, -100); + sleep(1000); + + ensureHiddenTooltipPositionedCorrectly(); + assertEquals("", getTooltipElement().getText()); + + // Show tooltip again + mouse.mouseMove(textfieldCoordinates, 10, 10); + sleep(1000); + + ensureVisibleTooltipPositionedCorrectly(); + assertEquals("My tooltip", getTooltipElement().getText()); + + // Hide tooltip + mouse.mouseMove(textfieldCoordinates, -100, -100); + sleep(1000); + + ensureHiddenTooltipPositionedCorrectly(); + assertEquals("", getTooltipElement().getText()); + } + + private WebElement getTooltipElement() { + return getDriver().findElement(By.className("v-tooltip-text")); + } + + private WebElement getTooltipContainerElement() { + return getDriver().findElement(By.className("v-tooltip")); + } + + private void ensureVisibleTooltipPositionedCorrectly() { + WebElement textfield = vaadinElementById("tf1"); + int tooltipX = getTooltipContainerElement().getLocation().getX(); + int textfieldX = textfield.getLocation().getX(); + assertGreaterOrEqual("Tooltip should be positioned on the textfield (" + + tooltipX + " < " + textfieldX + ")", tooltipX, textfieldX); + } + + private void ensureHiddenTooltipPositionedCorrectly() { + int tooltipX = getTooltipContainerElement().getLocation().getX(); + assertLessThanOrEqual( + "Tooltip should be positioned outside of viewport (was at " + + tooltipX + ")", tooltipX, -1000); + } +} diff --git a/uitest/src/com/vaadin/tests/integration/JSPIntegrationTest.java b/uitest/src/com/vaadin/tests/integration/JSPIntegrationTest.java new file mode 100644 index 0000000000..c5d6a65d87 --- /dev/null +++ b/uitest/src/com/vaadin/tests/integration/JSPIntegrationTest.java @@ -0,0 +1,100 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.integration; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.PrivateTB3Configuration; + +public class JSPIntegrationTest extends PrivateTB3Configuration { + + final String appRunnerTestUrl = getBaseURL() + "/run/Buttons"; + final String jspUrl = getBaseURL() + "/statictestfiles/vaadinsessions.jsp"; + final String integrationUrl = getBaseURL() + "/integration"; + + @Test + public void listVaadinSessions() { + + assertUICount(0); + + // Open a new UI + getDriver().get(integrationUrl); + assertUICount(1); + + // Open a new UI + getDriver().get(integrationUrl); + + // Should now have two UIs for the same service with different uiIds + List<UIData> twoUIs = getUIs(); + assertEquals(2, twoUIs.size()); + assertNotEquals(twoUIs.get(0).uiId, twoUIs.get(1).uiId); + assertEquals(twoUIs.get(0).serviceName, twoUIs.get(1).serviceName); + + getDriver().get(appRunnerTestUrl); + // Should now have two services with 2 + 1 UIs + List<UIData> threeUIs = getUIs(); + assertEquals(3, threeUIs.size()); + Set<String> serviceNames = new HashSet<String>(); + Set<Integer> uiIds = new HashSet<Integer>(); + for (UIData uiData : threeUIs) { + serviceNames.add(uiData.serviceName); + uiIds.add(uiData.uiId); + } + assertGreaterOrEqual( + "There should be at least two unique service names", + serviceNames.size(), 2); + assertGreaterOrEqual("There should be at least two unique ui ids", + uiIds.size(), 2); + } + + private static class UIData { + private String serviceName; + private int uiId; + } + + private List<UIData> getUIs() { + List<UIData> uis = new ArrayList<UIData>(); + + getDriver().get(jspUrl); + List<WebElement> rows = getDriver().findElements( + By.xpath("//tr[@class='uirow']")); + for (WebElement row : rows) { + UIData data = new UIData(); + List<WebElement> tds = row.findElements(By.xpath("./td")); + + data.serviceName = tds.get(0).getText(); + data.uiId = Integer.parseInt(tds.get(2).getText()); + + uis.add(data); + } + + return uis; + } + + private void assertUICount(int i) { + assertEquals(i, getUIs().size()); + } +} diff --git a/uitest/src/com/vaadin/tests/push/BasicPushLongPolling.java b/uitest/src/com/vaadin/tests/push/BasicPushLongPolling.java new file mode 100644 index 0000000000..bbb7895f20 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/BasicPushLongPolling.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +import com.vaadin.annotations.Push; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.ui.Transport; +import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; + +@Push(transport = Transport.LONG_POLLING) +public class BasicPushLongPolling extends BasicPush { + + @Override + public void init(VaadinRequest request) { + super.init(request); + // Don't use fallback so we can easier detect if long polling fails + getPushConfiguration().setParameter( + PushConfigurationState.FALLBACK_TRANSPORT_PARAM, "none"); + } + +} diff --git a/uitest/src/com/vaadin/tests/push/BasicPushLongPollingTest.java b/uitest/src/com/vaadin/tests/push/BasicPushLongPollingTest.java new file mode 100644 index 0000000000..b526a11d38 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/BasicPushLongPollingTest.java @@ -0,0 +1,19 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +public class BasicPushLongPollingTest extends BasicPushTest { +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/push/BasicPushTest.java b/uitest/src/com/vaadin/tests/push/BasicPushTest.java index ef40ae09dc..e03262ca7e 100644 --- a/uitest/src/com/vaadin/tests/push/BasicPushTest.java +++ b/uitest/src/com/vaadin/tests/push/BasicPushTest.java @@ -25,7 +25,7 @@ import com.vaadin.tests.tb3.MultiBrowserTest; public abstract class BasicPushTest extends MultiBrowserTest { @Test - public void testPush() { + public void testPush() throws InterruptedException { openTestURL(); // Test client initiated push diff --git a/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTime.java b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTime.java new file mode 100644 index 0000000000..d90394d3b5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTime.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +import com.vaadin.server.VaadinRequest; + +public abstract class ExtremelyLongPushTime extends PushLargeData { + + private static final int DURATION_MS = 48 * 60 * 60 * 1000; // 48 H + private static int INTERVAL_MS = 60 * 1000; // 1 minute + private static int PAYLOAD_SIZE = 100 * 1024; // 100 KB + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server. + * VaadinRequest) + */ + @Override + protected void setup(VaadinRequest request) { + super.setup(request); + duration.setConvertedValue(DURATION_MS); + interval.setConvertedValue(INTERVAL_MS); + dataSize.setConvertedValue(PAYLOAD_SIZE); + } + + @Override + protected String getTestDescription() { + return "Test which pushes data every minute for 48 hours"; + } + + @Override + protected Integer getTicketNumber() { + return null; + } + +} diff --git a/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeStreaming.java b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeStreaming.java new file mode 100644 index 0000000000..3e9582740d --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeStreaming.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +import com.vaadin.annotations.Push; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.ui.Transport; +import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; + +@Push(transport = Transport.STREAMING) +public class ExtremelyLongPushTimeStreaming extends ExtremelyLongPushTime { + + @Override + public void init(VaadinRequest request) { + super.init(request); + // Don't use fallback so we can easier detect failures + getPushConfiguration().setParameter( + PushConfigurationState.FALLBACK_TRANSPORT_PARAM, "none"); + } +} diff --git a/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeStreamingTest.java b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeStreamingTest.java new file mode 100644 index 0000000000..17837cb2d3 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeStreamingTest.java @@ -0,0 +1,21 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +public class ExtremelyLongPushTimeStreamingTest extends + ExtremelyLongPushTimeTest { + +} diff --git a/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeTest.java b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeTest.java new file mode 100644 index 0000000000..a1ce4b9d8f --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.support.ui.ExpectedConditions; + +import com.vaadin.tests.tb3.ExcludeFromSuite; +import com.vaadin.tests.tb3.MultiBrowserTest; + +@ExcludeFromSuite +public abstract class ExtremelyLongPushTimeTest extends MultiBrowserTest { + + private static final int ONE_HOUR_IN_MS = 20 * 1000; + + @Test + public void test24HourPush() throws Exception { + openTestURL(); + + // Without this there is a large chance that we will wait for all pushes + // to complete before moving on + testBench(driver).disableWaitForVaadin(); + + // Wait for startButton to be present + waitForElementToBePresent(vaadinLocatorById("startButton")); + + String logRow0Id = "Log_row_0"; + By logRow0 = vaadinLocatorById(logRow0Id); + + // Start the test + vaadinElementById("startButton").click(); + + // Wait for push to start. Should take 60s + waitUntil(ExpectedConditions.textToBePresentInElement(logRow0, + "Package "), 120); + + // Check every hour that push is still going on + for (int i = 0; i < 24; i++) { + sleep(ONE_HOUR_IN_MS); + ensureStillPushing(logRow0); + } + + } + + private void ensureStillPushing(By logRow0) { + String logValue = getDriver().findElement(logRow0).getText(); + // Wait for the log value to change. Should take max 60s + waitUntilNot( + ExpectedConditions.textToBePresentInElement(logRow0, logValue), + 120); + } + +} diff --git a/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeWebsocket.java b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeWebsocket.java new file mode 100644 index 0000000000..8346d49234 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeWebsocket.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +import com.vaadin.annotations.Push; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.ui.Transport; +import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; + +@Push(transport = Transport.WEBSOCKET) +public class ExtremelyLongPushTimeWebsocket extends ExtremelyLongPushTime { + + @Override + public void init(VaadinRequest request) { + super.init(request); + // Don't use fallback so we can easier detect if websocket fails + getPushConfiguration().setParameter( + PushConfigurationState.FALLBACK_TRANSPORT_PARAM, "none"); + } + +} diff --git a/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeWebsocketTest.java b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeWebsocketTest.java new file mode 100644 index 0000000000..23d773c7da --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/ExtremelyLongPushTimeWebsocketTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +import java.util.List; + +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.tests.tb3.WebsocketTest; + +public class ExtremelyLongPushTimeWebsocketTest extends + ExtremelyLongPushTimeTest { + + @Override + public List<DesiredCapabilities> getBrowsersToTest() { + return WebsocketTest.getWebsocketBrowsers(); + } +} diff --git a/uitest/src/com/vaadin/tests/push/IdlePushChannelStreamingTest.java b/uitest/src/com/vaadin/tests/push/IdlePushChannelStreamingTest.java new file mode 100644 index 0000000000..f9a0a722e5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/IdlePushChannelStreamingTest.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +public class IdlePushChannelStreamingTest extends IdlePushChannelTest { + @Override + protected Class<?> getUIClass() { + return BasicPushStreaming.class; + } +} diff --git a/uitest/src/com/vaadin/tests/push/IdlePushChannelTest.java b/uitest/src/com/vaadin/tests/push/IdlePushChannelTest.java new file mode 100644 index 0000000000..4dcc8a680d --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/IdlePushChannelTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public abstract class IdlePushChannelTest extends MultiBrowserTest { + + private static final int SEVEN_MINUTES_IN_MS = 7 * 60 * 1000; + + @Test + public void longWaitBetweenActions() throws Exception { + openTestURL(); + BasicPushTest.getIncrementButton(this).click(); + Assert.assertEquals(1, BasicPushTest.getClientCounter(this)); + sleep(SEVEN_MINUTES_IN_MS); + BasicPushTest.getIncrementButton(this).click(); + Assert.assertEquals(2, BasicPushTest.getClientCounter(this)); + } + +} diff --git a/uitest/src/com/vaadin/tests/push/IdlePushChannelWebsocketTest.java b/uitest/src/com/vaadin/tests/push/IdlePushChannelWebsocketTest.java new file mode 100644 index 0000000000..3fd9c616fb --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/IdlePushChannelWebsocketTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +import java.util.List; + +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.tests.tb3.WebsocketTest; + +public class IdlePushChannelWebsocketTest extends IdlePushChannelTest { + + @Override + protected Class<?> getUIClass() { + return BasicPushWebsocket.class; + } + + @Override + public List<DesiredCapabilities> getBrowsersToTest() { + return WebsocketTest.getWebsocketBrowsers(); + } +} diff --git a/uitest/src/com/vaadin/tests/push/LongPollingReconnectTest.java b/uitest/src/com/vaadin/tests/push/LongPollingReconnectTest.java new file mode 100644 index 0000000000..81c974e1e5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/LongPollingReconnectTest.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +public class LongPollingReconnectTest extends PushReconnectTest { + + @Override + protected Class<?> getUIClass() { + return BasicPushLongPolling.class; + } + +} diff --git a/uitest/src/com/vaadin/tests/push/PushFromInit.java b/uitest/src/com/vaadin/tests/push/PushFromInit.java index cb084f1232..0afaa866f7 100644 --- a/uitest/src/com/vaadin/tests/push/PushFromInit.java +++ b/uitest/src/com/vaadin/tests/push/PushFromInit.java @@ -15,29 +15,60 @@ */ package com.vaadin.tests.push; +import com.vaadin.annotations.Push; import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractTestUIWithLog; import com.vaadin.ui.Button; +@Push public class PushFromInit extends AbstractTestUIWithLog { + public static final String LOG_DURING_INIT = "Logged from access run before init ends"; + public static final String LOG_AFTER_INIT = "Logged from background thread run after init has finished"; + @Override protected void setup(VaadinRequest request) { - new Thread() { - @Override - public void run() { - access(new Runnable() { - @Override - public void run() { - log("Logged from background thread started in init"); - } - }); - } - }.start(); log("Logged in init"); + Thread t = new Thread(new RunBeforeInitEnds()); + t.start(); + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + new Thread(new RunAfterInit()).start(); addComponent(new Button("Sync")); } + class RunBeforeInitEnds implements Runnable { + @Override + public void run() { + access(new Runnable() { + @Override + public void run() { + log(LOG_DURING_INIT); + } + }); + } + } + + class RunAfterInit implements Runnable { + @Override + public void run() { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + access(new Runnable() { + @Override + public void run() { + log(LOG_AFTER_INIT); + } + }); + } + } + @Override protected String getTestDescription() { return "Pusing something to a newly created UI should not cause race conditions"; diff --git a/uitest/src/com/vaadin/tests/push/PushFromInitTest.java b/uitest/src/com/vaadin/tests/push/PushFromInitTest.java index 3c1bc1b610..4101de29cf 100644 --- a/uitest/src/com/vaadin/tests/push/PushFromInitTest.java +++ b/uitest/src/com/vaadin/tests/push/PushFromInitTest.java @@ -15,8 +15,9 @@ */ package com.vaadin.tests.push; -import org.junit.Assert; import org.junit.Test; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.ui.ExpectedCondition; import com.vaadin.tests.tb3.MultiBrowserTest; @@ -25,26 +26,13 @@ public class PushFromInitTest extends MultiBrowserTest { public void testPushFromInit() { openTestURL(); - for (int second = 0;; second++) { - if (second >= 30) { - Assert.fail("timeout"); + waitUntil(new ExpectedCondition<Boolean>() { + @Override + public Boolean apply(WebDriver input) { + return ("3. " + PushFromInit.LOG_AFTER_INIT) + .equals(getLogRow(0)); } - try { - if ("1. Logged in init".equals(vaadinElementById( - "Log_row_1").getText())) { - break; - } - } catch (Exception e) { - } - try { - Thread.sleep(200); - } catch (InterruptedException e) { - } - } - - Assert.assertEquals( - "2. Logged from background thread started in init", - vaadinElementById("Log_row_0").getText()); + }); } }
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/push/PushLargeData.java b/uitest/src/com/vaadin/tests/push/PushLargeData.java index 3b72424b32..83f573ed2c 100644 --- a/uitest/src/com/vaadin/tests/push/PushLargeData.java +++ b/uitest/src/com/vaadin/tests/push/PushLargeData.java @@ -51,14 +51,20 @@ public abstract class PushLargeData extends AbstractTestUIWithLog { private final ExecutorService executor = Executors .newSingleThreadExecutor(); + protected TextField dataSize; + + protected TextField interval; + + protected TextField duration; + @Override protected void setup(VaadinRequest request) { dataLabel.setSizeUndefined(); - final TextField dataSize = new TextField("Data size"); + dataSize = new TextField("Data size"); dataSize.setConverter(Integer.class); - final TextField interval = new TextField("Interval (ms)"); + interval = new TextField("Interval (ms)"); interval.setConverter(Integer.class); - final TextField duration = new TextField("Duration (ms)"); + duration = new TextField("Duration (ms)"); duration.setConverter(Integer.class); dataSize.setValue(DEFAULT_SIZE_BYTES + ""); diff --git a/uitest/src/com/vaadin/tests/push/PushLargeDataLongPolling.java b/uitest/src/com/vaadin/tests/push/PushLargeDataLongPolling.java new file mode 100644 index 0000000000..52a647115a --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushLargeDataLongPolling.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +import com.vaadin.annotations.Push; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.ui.Transport; +import com.vaadin.shared.ui.ui.UIState.PushConfigurationState; + +@Push(transport = Transport.LONG_POLLING) +public class PushLargeDataLongPolling extends PushLargeData { + + @Override + protected void setup(VaadinRequest request) { + super.setup(request); + getPushConfiguration().setParameter( + PushConfigurationState.FALLBACK_TRANSPORT_PARAM, "none"); + } +} diff --git a/uitest/src/com/vaadin/tests/push/PushLargeDataLongPollingTest.java b/uitest/src/com/vaadin/tests/push/PushLargeDataLongPollingTest.java new file mode 100644 index 0000000000..534c5287bb --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushLargeDataLongPollingTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.push; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.support.ui.ExpectedConditions; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class PushLargeDataLongPollingTest extends MultiBrowserTest { + + @Test + public void testLongPollingLargeData() throws Exception { + openTestURL(); + + // Without this there is a large chance that we will wait for all pushes + // to complete before moving on + testBench(driver).disableWaitForVaadin(); + + push(); + // Push complete. Browser will reconnect now as > 10MB has been sent + // Push again to ensure push still works + push(); + + } + + private void push() throws InterruptedException { + // Wait for startButton to be present + waitForElementToBePresent(vaadinLocatorById("startButton")); + + String logRow0Id = "Log_row_0"; + By logRow0 = vaadinLocatorById(logRow0Id); + + vaadinElementById("startButton").click(); + // Wait for push to start + waitUntil(ExpectedConditions.textToBePresentInElement(logRow0, + "Package ")); + + // Wait for until push should be done + sleep(PushLargeData.DEFAULT_DURATION_MS); + + // Wait until push is actually done + waitUntil(ExpectedConditions.textToBePresentInElement(logRow0, + "Push complete")); + } + +} diff --git a/uitest/src/com/vaadin/tests/push/PushLargeDataStreamingTest.java b/uitest/src/com/vaadin/tests/push/PushLargeDataStreamingTest.java index 8f10f0fbba..0d71c21118 100644 --- a/uitest/src/com/vaadin/tests/push/PushLargeDataStreamingTest.java +++ b/uitest/src/com/vaadin/tests/push/PushLargeDataStreamingTest.java @@ -24,7 +24,7 @@ import com.vaadin.tests.tb3.MultiBrowserTest; public class PushLargeDataStreamingTest extends MultiBrowserTest { @Test - public void testStreamingLargeData() { + public void testStreamingLargeData() throws InterruptedException { openTestURL(); // Without this there is a large chance that we will wait for all pushes @@ -38,7 +38,7 @@ public class PushLargeDataStreamingTest extends MultiBrowserTest { } - private void push() { + private void push() throws InterruptedException { // Wait for startButton to be present waitForElementToBePresent(vaadinLocatorById("startButton")); diff --git a/uitest/src/com/vaadin/tests/push/PushLargeDataWebsocketTest.java b/uitest/src/com/vaadin/tests/push/PushLargeDataWebsocketTest.java index 70a94f743e..cc8668a729 100644 --- a/uitest/src/com/vaadin/tests/push/PushLargeDataWebsocketTest.java +++ b/uitest/src/com/vaadin/tests/push/PushLargeDataWebsocketTest.java @@ -24,7 +24,7 @@ import com.vaadin.tests.tb3.WebsocketTest; public class PushLargeDataWebsocketTest extends WebsocketTest { @Test - public void testWebsocketLargeData() { + public void testWebsocketLargeData() throws Exception { openTestURL(); // Without this timing will be completly off as pushing "start" can @@ -38,7 +38,7 @@ public class PushLargeDataWebsocketTest extends WebsocketTest { } - private void push() { + private void push() throws Exception { // Wait for startButton to be present waitForElementToBePresent(vaadinLocatorById("startButton")); diff --git a/uitest/src/com/vaadin/tests/push/TogglePushTest.java b/uitest/src/com/vaadin/tests/push/TogglePushTest.java index 68d6f52b9f..1867f4a63a 100644 --- a/uitest/src/com/vaadin/tests/push/TogglePushTest.java +++ b/uitest/src/com/vaadin/tests/push/TogglePushTest.java @@ -24,7 +24,7 @@ import com.vaadin.tests.tb3.MultiBrowserTest; public class TogglePushTest extends MultiBrowserTest { @Test - public void togglePushInInit() { + public void togglePushInInit() throws Exception { setPush(true); String url = getTestUrl(); @@ -58,7 +58,7 @@ public class TogglePushTest extends MultiBrowserTest { } @Test - public void togglePush() { + public void togglePush() throws InterruptedException { setPush(true); openTestURL(); getDelayedCounterUpdateButton().click(); diff --git a/uitest/src/com/vaadin/tests/serialization/SerializerTest.html b/uitest/src/com/vaadin/tests/serialization/SerializerTest.html deleted file mode 100644 index 63219de5c2..0000000000 --- a/uitest/src/com/vaadin/tests/serialization/SerializerTest.html +++ /dev/null @@ -1,116 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://localhost:8888/" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.serialization.SerializerTest?restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[18]</td> - <td>sendBeanSubclass: 43</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[17]</td> - <td>sendBoolean: false, false, [false, false, true, false, true, true]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[16]</td> - <td>sendByte: 5, -12, [3, 1, 2]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[15]</td> - <td>sendChar: Å, ∫, [a, b, c, d]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[14]</td> - <td>sendInt: 2, 5, [2147483647, 0]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[13]</td> - <td>sendLong: -57841235865, 577431841358, [57, 0]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[12]</td> - <td>sendFloat: 1.0000001, 3.14159, [-12.0, 0.0, 57.0]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[11]</td> - <td>sendDouble: 0.423310825130748, 5.859874482048838, [2.0, 1.7976931348623157E308, 4.9E-324]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[10]</td> - <td>sendString: Taegghiiiinnrsssstt‡</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[9]</td> - <td>sendConnector: com.vaadin.tests.widgetset.server.SerializerTestExtension</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[8]</td> - <td>sendBean: ComplexTestBean [innerBean1=SimpleTestBean(1), innerBean2=SimpleTestBean(3), innerBeanCollection=[SimpleTestBean(6), SimpleTestBean(0)], privimite=6], SimpleTestBean(0), [SimpleTestBean(7)]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[7]</td> - <td>sendNull: null, Not null</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[6]</td> - <td>sendNestedArray: [[7, 5]], [[SimpleTestBean(2)], [SimpleTestBean(4)]]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[5]</td> - <td>sendList: [-234, 5, 8], class com.vaadin.tests.widgetset.server.SerializerTestExtension, class com.vaadin.tests.serialization.SerializerTest, [SimpleTestBean(-568), SimpleTestBean(234)]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[4]</td> - <td>sendArrayList: [[2], [2]], [[2, 1], [2, 3]], [[SimpleTestBean(7)]]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[3]</td> - <td>sendSet: [-12, -7, -4], class com.vaadin.tests.serialization.SerializerTest, [SimpleTestBean(2), SimpleTestBean(3)]</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[2]</td> - <td>sendMap: {a=SimpleTestBean(1)}, [com.vaadin.tests.widgetset.server.SerializerTestExtension=SimpleTestBean(4)], [2=com.vaadin.tests.widgetset.server.SerializerTestExtension], {SimpleTestBean(4)=SimpleTestBean(-4), SimpleTestBean(-5)=SimpleTestBean(5)}</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[1]</td> - <td>sendWrappedGenerics: {[SimpleTestBean(1)]={1=[SimpleTestBean(42)]}}</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestsserializationSerializerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[0]</td> - <td>sendEnum: PREFORMATTED, [HTML, RAW], [PREFORMATTED, XML]</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/serialization/SerializerTest.java b/uitest/src/com/vaadin/tests/serialization/SerializerTest.java index 0561f73b21..d4849ce667 100644 --- a/uitest/src/com/vaadin/tests/serialization/SerializerTest.java +++ b/uitest/src/com/vaadin/tests/serialization/SerializerTest.java @@ -16,15 +16,19 @@ package com.vaadin.tests.serialization; +import java.text.DateFormat; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.TimeZone; import com.vaadin.annotations.Widgetset; import com.vaadin.server.VaadinRequest; @@ -137,6 +141,8 @@ public class SerializerTest extends AbstractTestUI { ContentMode.PREFORMATTED, ContentMode.XML }, Arrays.asList(ContentMode.HTML, ContentMode.RAW)); + rpc.sendDate(new Date(1)); + rpc.sendDate(new Date(2013 - 1900, 5 - 1, 31, 11, 12, 13)); testExtension.registerRpc(new SerializerTestRpc() { @Override public void sendBoolean(boolean value, Boolean boxedValue, @@ -316,6 +322,15 @@ public class SerializerTest extends AbstractTestUI { log.log("sendBeanSubclass: " + bean.getValue()); } + @Override + public void sendDate(Date date) { + DateFormat format = DateFormat.getDateTimeInstance( + DateFormat.LONG, DateFormat.FULL, + new Locale("en", "fi")); + format.setTimeZone(TimeZone.getTimeZone("UTC")); + log.log("sendDate: " + format.format(date)); + } + }); } diff --git a/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java b/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java new file mode 100644 index 0000000000..d093a30ea7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.serialization; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class SerializerTestTest extends MultiBrowserTest { + + @Test + public void testSerialization() { + openTestURL(); + int logRow = 0; + + Assert.assertEquals("sendDate: May 31, 2013 8:12:13 AM UTC", + getLogRow(logRow++)); + Assert.assertEquals("sendDate: January 1, 1970 12:00:00 AM UTC", + getLogRow(logRow++)); + Assert.assertEquals( + "sendEnum: PREFORMATTED, [HTML, RAW], [PREFORMATTED, XML]", + getLogRow(logRow++)); + Assert.assertEquals( + "sendWrappedGenerics: {[SimpleTestBean(1)]={1=[SimpleTestBean(42)]}}", + getLogRow(logRow++)); + Assert.assertEquals( + "sendMap: {a=SimpleTestBean(1)}, [com.vaadin.tests.widgetset.server.SerializerTestExtension=SimpleTestBean(4)], [2=com.vaadin.tests.widgetset.server.SerializerTestExtension], {SimpleTestBean(4)=SimpleTestBean(-4), SimpleTestBean(-5)=SimpleTestBean(5)}", + getLogRow(logRow++)); + Assert.assertEquals( + "sendSet: [-12, -7, -4], class com.vaadin.tests.serialization.SerializerTest, [SimpleTestBean(2), SimpleTestBean(3)]", + getLogRow(logRow++)); + Assert.assertEquals( + "sendArrayList: [[2], [2]], [[2, 1], [2, 3]], [[SimpleTestBean(7)]]", + getLogRow(logRow++)); + Assert.assertEquals( + "sendList: [-234, 5, 8], class com.vaadin.tests.widgetset.server.SerializerTestExtension, class com.vaadin.tests.serialization.SerializerTest, [SimpleTestBean(-568), SimpleTestBean(234)]", + getLogRow(logRow++)); + Assert.assertEquals( + "sendNestedArray: [[7, 5]], [[SimpleTestBean(2)], [SimpleTestBean(4)]]", + getLogRow(logRow++)); + Assert.assertEquals("sendNull: null, Not null", getLogRow(logRow++)); + Assert.assertEquals( + "sendBean: ComplexTestBean [innerBean1=SimpleTestBean(1), innerBean2=SimpleTestBean(3), innerBeanCollection=[SimpleTestBean(6), SimpleTestBean(0)], privimite=6], SimpleTestBean(0), [SimpleTestBean(7)]", + getLogRow(logRow++)); + Assert.assertEquals( + "sendConnector: com.vaadin.tests.widgetset.server.SerializerTestExtension", + getLogRow(logRow++)); + Assert.assertEquals("sendString: Taegghiiiinnrsssstt‡", + getLogRow(logRow++)); + Assert.assertEquals( + "sendDouble: 0.423310825130748, 5.859874482048838, [2.0, 1.7976931348623157E308, 4.9E-324]", + getLogRow(logRow++)); + Assert.assertEquals( + "sendFloat: 1.0000001, 3.14159, [-12.0, 0.0, 57.0]", + getLogRow(logRow++)); + Assert.assertEquals("sendLong: -57841235865, 577431841358, [57, 0]", + getLogRow(logRow++)); + Assert.assertEquals("sendInt: 2, 5, [2147483647, 0]", + getLogRow(logRow++)); + Assert.assertEquals("sendChar: Å, ∫, [a, b, c, d]", getLogRow(logRow++)); + Assert.assertEquals("sendByte: 5, -12, [3, 1, 2]", getLogRow(logRow++)); + Assert.assertEquals( + "sendBoolean: false, false, [false, false, true, false, true, true]", + getLogRow(logRow++)); + Assert.assertEquals("sendBeanSubclass: 43", getLogRow(logRow++)); + } +} diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java index d7b7cd050f..55a2b80918 100644 --- a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java +++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java @@ -28,9 +28,13 @@ import org.junit.After; import org.junit.Before; import org.junit.runner.RunWith; import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.Platform; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.HasInputDevices; +import org.openqa.selenium.interactions.Keyboard; +import org.openqa.selenium.interactions.Mouse; import org.openqa.selenium.remote.BrowserType; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; @@ -74,6 +78,11 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { */ private static final int SCREENSHOT_WIDTH = 1500; + /** + * Timeout used by the TB grid + */ + private static final int BROWSER_TIMEOUT_IN_MS = 30 * 1000; + private DesiredCapabilities desiredCapabilities; private boolean debug = false; @@ -270,6 +279,21 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { } /** + * Uses JavaScript to determine the currently focused element. + * + * @return Focused element or null + */ + protected WebElement getFocusedElement() { + Object focusedElement = ((JavascriptExecutor) getDriver()) + .executeScript("return document.activeElement"); + if (null != focusedElement) { + return (WebElement) focusedElement; + } else { + return null; + } + } + + /** * Find a Vaadin element based on its id given using Component.setId * * @param id @@ -641,17 +665,21 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { } /** - * Helper method for sleeping X ms in a test. Catches and ignores - * InterruptedExceptions + * Sleeps for the given number of ms but ensures that the browser connection + * does not time out. * * @param timeoutMillis * Number of ms to wait + * @throws InterruptedException */ - protected void sleep(int timeoutMillis) { - try { - Thread.sleep(timeoutMillis); - } catch (InterruptedException e) { - throw new RuntimeException(e); + protected void sleep(int timeoutMillis) throws InterruptedException { + while (timeoutMillis > 0) { + int d = Math.min(BROWSER_TIMEOUT_IN_MS, timeoutMillis); + Thread.sleep(d); + timeoutMillis -= d; + + // Do something to keep the connection alive + getDriver().getTitle(); } } @@ -882,4 +910,22 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { } + /** + * Returns the mouse object for doing mouse commands + * + * @return Returns the mouse + */ + public Mouse getMouse() { + return ((HasInputDevices) getDriver()).getMouse(); + } + + /** + * Returns the keyboard object for controlling keyboard events + * + * @return Return the keyboard + */ + public Keyboard getKeyboard() { + return ((HasInputDevices) getDriver()).getKeyboard(); + } + } diff --git a/uitest/src/com/vaadin/tests/tb3/ExcludeFromSuite.java b/uitest/src/com/vaadin/tests/tb3/ExcludeFromSuite.java new file mode 100644 index 0000000000..722b643f78 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/ExcludeFromSuite.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.tb3; + +/** + * Marker interface for a TB3+ test class which will exclude the test from any + * test suite which automatically scans for test classes. Mostly useful for long + * tests which should not be run in every build. + * + * @since 7.1.10 + * @author Vaadin Ltd + */ +public @interface ExcludeFromSuite { + +} diff --git a/uitest/src/com/vaadin/tests/tb3/TB3TestSuite.java b/uitest/src/com/vaadin/tests/tb3/TB3TestSuite.java index e1c8edfd60..f1576a9393 100644 --- a/uitest/src/com/vaadin/tests/tb3/TB3TestSuite.java +++ b/uitest/src/com/vaadin/tests/tb3/TB3TestSuite.java @@ -223,6 +223,10 @@ public class TB3TestSuite extends Suite { if (!baseClass.isAssignableFrom(c)) { return; } + if (!includeInSuite(c)) { + return; + } + if (!Modifier.isAbstract(c.getModifiers()) && !c.isAnonymousClass()) { result.add((Class<? extends T>) c); } @@ -235,4 +239,18 @@ public class TB3TestSuite extends Suite { } + /** + * @return true if the class should be included in the suite, false if not + */ + private static boolean includeInSuite(Class<?> c) { + if (c.getAnnotation(ExcludeFromSuite.class) != null) { + return false; + } + if (c == Object.class) { + return true; + } + + return includeInSuite(c.getSuperclass()); + } + }
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassConnector.java new file mode 100644 index 0000000000..fb28e94bfa --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassConnector.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.widgetset.client; + +import com.vaadin.client.ui.label.LabelConnector; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.MediaControl; +import com.vaadin.tests.widgetset.server.ClientRpcClassComponent; + +@Connect(ClientRpcClassComponent.class) +public class ClientRpcClassConnector extends LabelConnector { + + @Override + protected void init() { + super.init(); + registerRpc(MediaControl.class, getWidget()); + } + + @Override + public ClientRpcClassWidget getWidget() { + return (ClientRpcClassWidget) super.getWidget(); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassWidget.java new file mode 100644 index 0000000000..91b4f19d92 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassWidget.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.widgetset.client; + +import com.vaadin.client.ui.VLabel; +import com.vaadin.shared.ui.MediaControl; + +public class ClientRpcClassWidget extends VLabel implements MediaControl { + + @Override + public void play() { + setText("play"); + } + + @Override + public void pause() { + setText("pause"); + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java index 0f6ad577ed..01ec6cc4bb 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java @@ -19,6 +19,7 @@ package com.vaadin.tests.widgetset.client; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -251,6 +252,11 @@ public class SerializerTestConnector extends AbstractExtensionConnector { } }); } + + @Override + public void sendDate(Date date) { + rpc.sendDate(date); + } }); } diff --git a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestRpc.java b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestRpc.java index 4bda067242..fb5b6a1980 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestRpc.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestRpc.java @@ -16,6 +16,7 @@ package com.vaadin.tests.widgetset.client; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; @@ -79,4 +80,5 @@ public interface SerializerTestRpc extends ServerRpc, ClientRpc { public void sendBeanSubclass(SimpleTestBean bean); + public void sendDate(Date date); } diff --git a/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClass.java b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClass.java new file mode 100644 index 0000000000..cbc46b26f5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClass.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.widgetset.server; + +import com.vaadin.annotations.Widgetset; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.widgetset.TestingWidgetSet; + +@Widgetset(TestingWidgetSet.NAME) +public class ClientRpcClass extends AbstractTestUI { + + public static String TEST_COMPONENT_ID = "testComponent"; + + @Override + protected void setup(VaadinRequest request) { + ClientRpcClassComponent component = new ClientRpcClassComponent(); + component.setId(TEST_COMPONENT_ID); + addComponent(component); + + component.pause(); + } + + @Override + protected String getTestDescription() { + return "UI showing dummy component where the wiget type is implementing the RPC interface."; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(13056); + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassComponent.java b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassComponent.java new file mode 100644 index 0000000000..135f112fe4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassComponent.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.widgetset.server; + +import com.vaadin.shared.ui.MediaControl; +import com.vaadin.ui.Label; + +public class ClientRpcClassComponent extends Label { + public void play() { + getRpcProxy(MediaControl.class).play(); + } + + public void pause() { + getRpcProxy(MediaControl.class).pause(); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassTest.java b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassTest.java new file mode 100644 index 0000000000..16c5ba4b61 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 com.vaadin.tests.widgetset.server; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class ClientRpcClassTest extends MultiBrowserTest { + + @Test + public void pauseDisplayed() { + openTestURL(); + + WebElement element = getDriver().findElement( + By.id(ClientRpcClass.TEST_COMPONENT_ID)); + Assert.assertEquals("pause", element.getText()); + } +} |