001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.tools.seleniumbuilder;
016    
017    import com.liferay.portal.freemarker.FreeMarkerUtil;
018    import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
019    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
020    import com.liferay.portal.kernel.util.ArrayUtil;
021    import com.liferay.portal.kernel.util.CharPool;
022    import com.liferay.portal.kernel.util.FileUtil;
023    import com.liferay.portal.kernel.util.StringBundler;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.util.StringUtil;
026    import com.liferay.portal.kernel.util.TextFormatter;
027    import com.liferay.portal.kernel.util.Validator;
028    import com.liferay.portal.kernel.xml.Attribute;
029    import com.liferay.portal.kernel.xml.Document;
030    import com.liferay.portal.kernel.xml.DocumentException;
031    import com.liferay.portal.kernel.xml.Element;
032    import com.liferay.portal.kernel.xml.SAXReaderUtil;
033    import com.liferay.portal.tools.servicebuilder.ServiceBuilder;
034    
035    import java.io.File;
036    
037    import java.util.ArrayList;
038    import java.util.HashMap;
039    import java.util.HashSet;
040    import java.util.List;
041    import java.util.Map;
042    import java.util.Set;
043    import java.util.TreeSet;
044    import java.util.regex.Matcher;
045    import java.util.regex.Pattern;
046    
047    /**
048     * @author Michael Hashimoto
049     */
050    public class SeleniumBuilderFileUtil {
051    
052            public SeleniumBuilderFileUtil(String baseDir) {
053                    _baseDir = baseDir;
054            }
055    
056            public List<Element> getAllChildElements(
057                    Element element, String elementName) {
058    
059                    List<Element> allChildElements = new ArrayList<Element>();
060    
061                    List<Element> childElements = element.elements();
062    
063                    if (childElements.isEmpty()) {
064                            return allChildElements;
065                    }
066    
067                    for (Element childElement : childElements) {
068                            String childElementName = childElement.getName();
069    
070                            if (childElementName.equals(elementName)) {
071                                    allChildElements.add(childElement);
072                            }
073    
074                            allChildElements.addAll(
075                                    getAllChildElements(childElement, elementName));
076                    }
077    
078                    return allChildElements;
079            }
080    
081            public String getBaseDir() {
082                    return _baseDir;
083            }
084    
085            public Set<String> getChildElementAttributeValues(
086                    Element element, String attributeName) {
087    
088                    Set<String> childElementAttributeValues = new TreeSet<String>();
089    
090                    List<Element> childElements = element.elements();
091    
092                    if (childElements.isEmpty()) {
093                            return childElementAttributeValues;
094                    }
095    
096                    for (Element childElement : childElements) {
097                            String childElementName = childElement.attributeValue(
098                                    attributeName);
099    
100                            if (childElementName != null) {
101                                    int x = childElementName.lastIndexOf(StringPool.POUND);
102    
103                                    if (x != -1) {
104                                            childElementAttributeValues.add(
105                                                    childElementName.substring(0, x));
106                                    }
107                            }
108    
109                            childElementAttributeValues.addAll(
110                                    getChildElementAttributeValues(childElement, attributeName));
111                    }
112    
113                    return childElementAttributeValues;
114            }
115    
116            public String getClassName(String fileName) {
117                    String classSuffix = getClassSuffix(fileName);
118    
119                    return getClassName(fileName, classSuffix);
120            }
121    
122            public String getClassName(String fileName, String classSuffix) {
123                    return
124                            getPackageName(fileName) + "." +
125                                    getSimpleClassName(fileName, classSuffix);
126            }
127    
128            public String getClassSuffix(String fileName) {
129                    int x = fileName.indexOf(CharPool.PERIOD);
130    
131                    String classSuffix = StringUtil.upperCaseFirstLetter(
132                            fileName.substring(x + 1));
133    
134                    if (classSuffix.equals("Testcase")) {
135                            classSuffix = "TestCase";
136                    }
137                    else if (classSuffix.equals("Testsuite")) {
138                            classSuffix = "TestSuite";
139                    }
140    
141                    return classSuffix;
142            }
143    
144            public String getJavaFileName(String fileName) {
145                    String classSuffix = getClassSuffix(fileName);
146    
147                    return getJavaFileName(fileName, classSuffix);
148            }
149    
150            public String getJavaFileName(String fileName, String classSuffix) {
151                    return
152                            getPackagePath(fileName) + "/" +
153                                    getSimpleClassName(fileName, classSuffix) + ".java";
154            }
155    
156            public int getLocatorCount(Element rootElement) {
157                    String xml = rootElement.asXML();
158    
159                    for (int i = 1;; i++) {
160                            if (xml.contains("${locator" + i + "}")) {
161                                    continue;
162                            }
163    
164                            if (i > 1) {
165                                    i--;
166                            }
167    
168                            return i;
169                    }
170            }
171    
172            public String getName(String fileName) {
173                    int x = fileName.lastIndexOf(StringPool.SLASH);
174                    int y = fileName.lastIndexOf(CharPool.PERIOD);
175    
176                    return fileName.substring(x + 1, y);
177            }
178    
179            public String getNormalizedContent(String fileName) throws Exception {
180                    String content = readFile(fileName);
181    
182                    if (fileName.endsWith(".path")) {
183                            int x = content.indexOf("<tbody>");
184                            int y = content.indexOf("</tbody>");
185    
186                            if ((x == -1) || (y == -1)) {
187                                    throwValidationException(1002, fileName, "tbody");
188                            }
189    
190                            String pathTbody = content.substring(x, y + 8);
191    
192                            Map<String, Object> context = new HashMap<String, Object>();
193    
194                            context.put("pathName", getName(fileName));
195                            context.put("pathTbody", pathTbody);
196    
197                            String newContent = processTemplate("path_xml.ftl", context);
198    
199                            if (!content.equals(newContent)) {
200                                    content = newContent;
201    
202                                    writeFile(getBaseDir(), fileName, newContent, false);
203                            }
204                    }
205    
206                    StringBundler sb = new StringBundler();
207    
208                    int lineNumber = 1;
209    
210                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
211                            new UnsyncStringReader(content));
212    
213                    String line = null;
214    
215                    while ((line = unsyncBufferedReader.readLine()) != null) {
216                            Pattern pattern = Pattern.compile("<[a-z\\-]+");
217    
218                            Matcher matcher = pattern.matcher(line);
219    
220                            if (matcher.find()) {
221                                    line = StringUtil.replace(
222                                            line, matcher.group(),
223                                            matcher.group() + " line-number=\"" + lineNumber + "\"");
224                            }
225    
226                            sb.append(line);
227    
228                            lineNumber++;
229                    }
230    
231                    content = sb.toString();
232    
233                    if (content != null) {
234                            content = content.trim();
235                            content = StringUtil.replace(content, "\n", "");
236                            content = StringUtil.replace(content, "\r\n", "");
237                            content = StringUtil.replace(content, "\t", " ");
238                            content = content.replaceAll(" +", " ");
239                    }
240    
241                    return content;
242            }
243    
244            public String getObjectName(String name) {
245                    return StringUtil.upperCaseFirstLetter(name);
246            }
247    
248            public String getPackageName(String fileName) {
249                    String packagePath = getPackagePath(fileName);
250    
251                    return StringUtil.replace(
252                            packagePath, StringPool.SLASH, StringPool.PERIOD);
253            }
254    
255            public String getPackagePath(String fileName) {
256                    int x = fileName.lastIndexOf(StringPool.SLASH);
257    
258                    return fileName.substring(0, x);
259            }
260    
261            public Set<String> getPathLocatorKeys(Element rootElement) {
262                    Set<String> pathLocatorKeys = new HashSet<String>();
263    
264                    Element bodyElement = rootElement.element("body");
265    
266                    Element tableElement = bodyElement.element("table");
267    
268                    Element tbodyElement = tableElement.element("tbody");
269    
270                    List<Element> trElements = tbodyElement.elements();
271    
272                    for (Element trElement : trElements) {
273                            Element tdElement = trElement.element("td");
274    
275                            pathLocatorKeys.add(tdElement.getText());
276                    }
277    
278                    return pathLocatorKeys;
279            }
280    
281            public String getReturnType(String name) {
282                    if (name.startsWith("Is")) {
283                            return "boolean";
284                    }
285    
286                    return "void";
287            }
288    
289            public Element getRootElement(String fileName) throws Exception {
290                    String content = getNormalizedContent(fileName);
291    
292                    try {
293                            Document document = SAXReaderUtil.read(content, true);
294    
295                            Element rootElement = document.getRootElement();
296    
297                            validate(fileName, rootElement);
298    
299                            return rootElement;
300                    }
301                    catch (DocumentException de) {
302                            throwValidationException(1007, fileName, de);
303                    }
304    
305                    return null;
306            }
307    
308            public String getSimpleClassName(String fileName) {
309                    String classSuffix = getClassSuffix(fileName);
310    
311                    return getSimpleClassName(fileName, classSuffix);
312            }
313    
314            public String getSimpleClassName(String fileName, String classSuffix) {
315                    return getName(fileName) + classSuffix;
316            }
317    
318            public String getVariableName(String name) {
319                    return TextFormatter.format(name, TextFormatter.I);
320            }
321    
322            public String normalizeFileName(String fileName) {
323                    return StringUtil.replace(
324                            fileName, StringPool.BACK_SLASH, StringPool.SLASH);
325            }
326    
327            public String readFile(String fileName) throws Exception {
328                    return FileUtil.read(getBaseDir() + "/" + fileName);
329            }
330    
331            public void writeFile(String fileName, String content, boolean format)
332                    throws Exception {
333    
334                    writeFile(getBaseDir() + "-generated", fileName, content, format);
335            }
336    
337            public void writeFile(
338                            String baseDir, String fileName, String content, boolean format)
339                    throws Exception {
340    
341                    File file = new File(baseDir + "/" + fileName);
342    
343                    if (format) {
344                            ServiceBuilder.writeFile(file, content);
345                    }
346                    else {
347                            System.out.println("Writing " + file);
348    
349                            FileUtil.write(file, content);
350                    }
351            }
352    
353            protected String processTemplate(String name, Map<String, Object> context)
354                    throws Exception {
355    
356                    return StringUtil.strip(
357                            FreeMarkerUtil.process(_TPL_ROOT + name, context), '\r');
358            }
359    
360            protected void throwValidationException(int errorCode, String fileName) {
361                    throwValidationException(
362                            errorCode, fileName, null, null, null, null, null);
363            }
364    
365            protected void throwValidationException(
366                    int errorCode, String fileName, Element element) {
367    
368                    throwValidationException(
369                            errorCode, fileName, element, null, null, null, null);
370            }
371    
372            protected void throwValidationException(
373                    int errorCode, String fileName, Element element, String string1) {
374    
375                    throwValidationException(
376                            errorCode, fileName, element, null, string1, null, null);
377            }
378    
379            protected void throwValidationException(
380                    int errorCode, String fileName, Element element, String string1,
381                    String string2) {
382    
383                    throwValidationException(
384                            errorCode, fileName, element, null, string1, string2, null);
385            }
386    
387            protected void throwValidationException(
388                    int errorCode, String fileName, Element element, String[] array) {
389    
390                    throwValidationException(
391                            errorCode, fileName, element, array, null, null, null);
392            }
393    
394            protected void throwValidationException(
395                    int errorCode, String fileName, Element element, String[] array,
396                    String string1, String string2, Exception e) {
397    
398                    String prefix = "Error " + errorCode + ": ";
399                    String suffix = fileName;
400    
401                    if (element != null) {
402                            suffix += ":" + element.attributeValue("line-number");
403                    }
404    
405                    if (errorCode == 1000) {
406                            throw new IllegalArgumentException(
407                                    prefix + "Invalid root element in " + suffix);
408                    }
409                    else if (errorCode == 1001) {
410                            throw new IllegalArgumentException(
411                                    prefix + "Missing (" + StringUtil.merge(array, "|") +
412                                            ") child element in " + suffix);
413                    }
414                    else if (errorCode == 1002) {
415                            throw new IllegalArgumentException(
416                                    prefix + "Invalid " + string1 + " element in " + suffix);
417                    }
418                    else if (errorCode == 1003) {
419                            throw new IllegalArgumentException(
420                                    prefix + "Missing " + string1 + " attribute in " + suffix);
421                    }
422                    else if (errorCode == 1004) {
423                            throw new IllegalArgumentException(
424                                    prefix + "Missing (" + StringUtil.merge(array, "|") +
425                                            ") attribute in " + suffix);
426                    }
427                    else if (errorCode == 1005) {
428                            throw new IllegalArgumentException(
429                                    prefix + "Invalid " + string1 + " attribute in " + suffix);
430                    }
431                    else if (errorCode == 1006) {
432                            throw new IllegalArgumentException(
433                                    prefix + "Invalid " + string1 + " attribute value in " +
434                                            suffix);
435                    }
436                    else if (errorCode == 1007) {
437                            throw new IllegalArgumentException(
438                                    prefix + "Poorly formed XML in " + suffix, e);
439                    }
440                    else if (errorCode == 1008) {
441                            throw new IllegalArgumentException(
442                                    prefix + "Duplicate file name " + string1 + " at " + suffix);
443                    }
444                    else if (errorCode == 1009) {
445                            throw new IllegalArgumentException(
446                                    prefix + "Duplicate command name " + string1 + " at " + suffix);
447                    }
448                    else if (errorCode == 1010) {
449                            throw new IllegalArgumentException(
450                                    prefix + "Invalid locator-key " + string1 + " at " + suffix);
451                    }
452                    else if (errorCode == 1011) {
453                            throw new IllegalArgumentException(
454                                    prefix + "Invalid " + string1 + " name " + string2 + " at " +
455                                            suffix);
456                    }
457                    else if (errorCode == 1012) {
458                            throw new IllegalArgumentException(
459                                    prefix + "Invalid " + string1 + " command " + string2 + " at " +
460                                            suffix);
461                    }
462                    else if (errorCode == 2000) {
463                            throw new IllegalArgumentException(
464                                    prefix + "Too many child elements in the " + string1 +
465                                            " element in " + suffix);
466                    }
467                    else if (errorCode == 2001) {
468                            throw new IllegalArgumentException(
469                                    prefix + "Action command " + string1 +
470                                            " does not match a function name at " + suffix);
471                    }
472                    else if (errorCode == 2002) {
473                            throw new IllegalArgumentException(
474                                    prefix + "Missing matching " + string1 + ".path for " + suffix);
475                    }
476                    else {
477                            throw new IllegalArgumentException(prefix + suffix);
478                    }
479            }
480    
481            protected void throwValidationException(
482                    int errorCode, String fileName, Exception e) {
483    
484                    throwValidationException(
485                            errorCode, fileName, null, null, null, null, e);
486            }
487    
488            protected void throwValidationException(
489                    int errorCode, String fileName, String string1) {
490    
491                    throwValidationException(
492                            errorCode, fileName, null, null, string1, null, null);
493            }
494    
495            protected void validate(String fileName, Element rootElement)
496                    throws Exception {
497    
498                    if (fileName.endsWith(".action")) {
499                            validateActionDocument(fileName, rootElement);
500                    }
501                    else if (fileName.endsWith(".function")) {
502                            validateFunctionDocument(fileName, rootElement);
503                    }
504                    else if (fileName.endsWith(".macro")) {
505                            validateMacroDocument(fileName, rootElement);
506                    }
507                    else if (fileName.endsWith(".path")) {
508                            validatePathDocument(fileName, rootElement);
509                    }
510                    else if (fileName.endsWith(".testcase")) {
511                            validateTestCaseDocument(fileName, rootElement);
512                    }
513                    else if (fileName.endsWith(".testsuite")) {
514                            validateTestSuiteDocument(fileName, rootElement);
515                    }
516            }
517    
518            protected void validateActionCommandElement(
519                    String fileName, Element commandElement,
520                    String[] allowedBlockChildElementNames,
521                    String[] allowedExecuteAttributeNames,
522                    String[] allowedExecuteChildElementNames) {
523    
524                    List<Element> elements = commandElement.elements();
525    
526                    if (elements.isEmpty()) {
527                            throwValidationException(
528                                    1001, fileName, commandElement,
529                                    new String[] {"case", "default"});
530                    }
531    
532                    for (Element element : elements) {
533                            List<Element> childElements = element.elements();
534    
535                            String elementName = element.getName();
536    
537                            if (childElements.size() > 1) {
538                                    throwValidationException(
539                                            2000, fileName, childElements.get(1), elementName);
540                            }
541    
542                            if (elementName.equals("case")) {
543                                    List<Attribute> attributes = element.attributes();
544    
545                                    boolean hasNeededAttributeName = false;
546    
547                                    for (Attribute attribute : attributes) {
548                                            String attributeName = attribute.getName();
549    
550                                            if (attributeName.equals("comparator")) {
551                                                    String attributeValue = attribute.getValue();
552    
553                                                    if (!attributeValue.equals("contains") &&
554                                                            !attributeValue.equals("endsWith") &&
555                                                            !attributeValue.equals("equals") &&
556                                                            !attributeValue.equals("startsWith")) {
557    
558                                                            throwValidationException(
559                                                                    1006, fileName, element, attributeName);
560                                                    }
561                                            }
562                                            else if (attributeName.startsWith("locator") ||
563                                                             attributeName.startsWith("locator-key")) {
564    
565                                                    String attributeValue = attribute.getValue();
566    
567                                                    if (Validator.isNull(attributeValue)) {
568                                                            throwValidationException(
569                                                                    1006, fileName, element, attributeName);
570                                                    }
571    
572                                                    hasNeededAttributeName = true;
573                                            }
574    
575                                            if (!attributeName.equals("comparator") &&
576                                                    !attributeName.equals("line-number") &&
577                                                    !attributeName.startsWith("locator") &&
578                                                    !attributeName.startsWith("locator-key")) {
579    
580                                                    throwValidationException(
581                                                            1005, fileName, element, attributeName);
582                                            }
583    
584                                            if (attributeName.equals("locator") ||
585                                                    attributeName.equals("locator-key")) {
586    
587                                                    throwValidationException(
588                                                            1005, fileName, element, attributeName);
589                                            }
590                                    }
591    
592                                    if (!hasNeededAttributeName) {
593                                            throwValidationException(
594                                                    1004, fileName, element,
595                                                    new String[] {"locator1", "locator-key1"});
596                                    }
597    
598                                    validateBlockElement(
599                                            fileName, element, new String[] {"execute"},
600                                            new String[] {"function"}, new String[0], new String[0]);
601                            }
602                            else if (elementName.equals("default")) {
603                                    List<Attribute> attributes = element.attributes();
604    
605                                    if (attributes.size() != 1) {
606                                            Attribute attribute = attributes.get(1);
607    
608                                            String attributeName = attribute.getName();
609    
610                                            throwValidationException(
611                                                    1005, fileName, element, attributeName);
612                                    }
613    
614                                    validateBlockElement(
615                                            fileName, element, new String[] {"execute"},
616                                            new String[] {"function"}, new String[0], new String[0]);
617                            }
618                            else {
619                                    throwValidationException(1002, fileName, element, elementName);
620                            }
621                    }
622            }
623    
624            protected void validateActionDocument(
625                    String fileName, Element rootElement) {
626    
627                    if (!Validator.equals(rootElement.getName(), "definition")) {
628                            throwValidationException(1000, fileName, rootElement);
629                    }
630    
631                    List<Element> elements = rootElement.elements();
632    
633                    if (elements.isEmpty()) {
634                            throwValidationException(
635                                    1001, fileName, rootElement, new String[] {"command"});
636                    }
637    
638                    for (Element element : elements) {
639                            String elementName = element.getName();
640    
641                            if (elementName.equals("command")) {
642                                    String attributeValue = element.attributeValue("name");
643    
644                                    if (attributeValue == null) {
645                                            throwValidationException(1003, fileName, element, "name");
646                                    }
647                                    else if (Validator.isNull(attributeValue)) {
648                                            throwValidationException(1006, fileName, element, "name");
649                                    }
650    
651                                    validateActionCommandElement(
652                                            fileName, element, new String[] {"execute"},
653                                            new String[] {"function"}, new String[0]);
654                            }
655                            else {
656                                    throwValidationException(1002, fileName, element, elementName);
657                            }
658                    }
659            }
660    
661            protected void validateBlockElement(
662                    String fileName, Element commandElement,
663                    String[] allowedBlockChildElementNames,
664                    String[] allowedExecuteAttributeNames,
665                    String[] allowedExecuteChildElementNames,
666                    String[] allowedIfConditionElementNames) {
667    
668                    List<Element> elements = commandElement.elements();
669    
670                    if (elements.isEmpty()) {
671                            throwValidationException(
672                                    1001, fileName, commandElement, allowedBlockChildElementNames);
673                    }
674    
675                    for (Element element : elements) {
676                            String elementName = element.getName();
677    
678                            if (!ArrayUtil.contains(
679                                            allowedBlockChildElementNames, elementName)) {
680    
681                                    throwValidationException(1002, fileName, element, elementName);
682                            }
683    
684                            if (elementName.equals("echo") || elementName.equals("fail")) {
685                                    validateSimpleElement(
686                                            fileName, element, new String[] {"message"});
687                            }
688                            else if (elementName.equals("execute")) {
689                                    validateExecuteElement(
690                                            fileName, element, allowedExecuteAttributeNames, ".+",
691                                            allowedExecuteChildElementNames);
692                            }
693                            else if (elementName.equals("if")) {
694                                    validateIfElement(
695                                            fileName, element, allowedBlockChildElementNames,
696                                            allowedExecuteAttributeNames,
697                                            allowedExecuteChildElementNames,
698                                            allowedIfConditionElementNames);
699                            }
700                            else if (elementName.equals("var")) {
701                                    validateSimpleElement(
702                                            fileName, element, new String[] {"name", "value"});
703                            }
704                            else if (elementName.equals("while")) {
705                                    validateWhileElement(
706                                            fileName, element, allowedBlockChildElementNames,
707                                            allowedExecuteAttributeNames,
708                                            allowedExecuteChildElementNames,
709                                            allowedIfConditionElementNames);
710                            }
711                            else {
712                                    throwValidationException(1002, fileName, element, elementName);
713                            }
714                    }
715            }
716    
717            protected void validateExecuteElement(
718                    String fileName, Element executeElement,
719                    String[] allowedExecuteAttributeNames,
720                    String allowedExecuteAttributeValuesRegex,
721                    String[] allowedExecuteChildElementNames) {
722    
723                    boolean hasAllowedAttributeName = false;
724    
725                    List<Attribute> attributes = executeElement.attributes();
726    
727                    for (Attribute attribute : attributes) {
728                            String attributeName = attribute.getName();
729    
730                            if (ArrayUtil.contains(
731                                            allowedExecuteAttributeNames, attributeName)) {
732    
733                                    hasAllowedAttributeName = true;
734    
735                                    break;
736                            }
737                    }
738    
739                    if (!hasAllowedAttributeName) {
740                            throwValidationException(
741                                    1004, fileName, executeElement, allowedExecuteAttributeNames);
742                    }
743    
744                    String action = executeElement.attributeValue("action");
745                    String function = executeElement.attributeValue("function");
746                    String macro = executeElement.attributeValue("macro");
747                    String selenium = executeElement.attributeValue("selenium");
748                    String testCase = executeElement.attributeValue("test-case");
749                    String testSuite = executeElement.attributeValue("test-suite");
750    
751                    if (action != null) {
752                            if (Validator.isNull(action) ||
753                                    !action.matches(allowedExecuteAttributeValuesRegex)) {
754    
755                                    throwValidationException(
756                                            1006, fileName, executeElement, "action");
757                            }
758    
759                            for (Attribute attribute : attributes) {
760                                    String attributeName = attribute.getName();
761    
762                                    if (!attributeName.equals("action") &&
763                                            !attributeName.equals("line-number") &&
764                                            !attributeName.startsWith("locator") &&
765                                            !attributeName.startsWith("locator-key") &&
766                                            !attributeName.startsWith("value")) {
767    
768                                            throwValidationException(
769                                                    1005, fileName, executeElement, attributeName);
770                                    }
771    
772                                    if (attributeName.equals("locator") ||
773                                            attributeName.equals("locator-key") ||
774                                            attributeName.equals("value")) {
775    
776                                            throwValidationException(
777                                                    1005, fileName, executeElement, attributeName);
778                                    }
779                            }
780                    }
781                    else if (function != null) {
782                            if (Validator.isNull(function) ||
783                                    !function.matches(allowedExecuteAttributeValuesRegex)) {
784    
785                                    throwValidationException(
786                                            1006, fileName, executeElement, "function");
787                            }
788    
789                            for (Attribute attribute : attributes) {
790                                    String attributeName = attribute.getName();
791    
792                                    if (!attributeName.equals("function") &&
793                                            !attributeName.equals("line-number") &&
794                                            !attributeName.startsWith("locator") &&
795                                            !attributeName.startsWith("value")) {
796    
797                                            throwValidationException(
798                                                    1005, fileName, executeElement, attributeName);
799                                    }
800    
801                                    if (attributeName.equals("locator") ||
802                                            attributeName.equals("value")) {
803    
804                                            throwValidationException(
805                                                    1005, fileName, executeElement, attributeName);
806                                    }
807                            }
808                    }
809                    else if (macro != null) {
810                            if (Validator.isNull(macro) ||
811                                    !macro.matches(allowedExecuteAttributeValuesRegex)) {
812    
813                                    throwValidationException(
814                                            1006, fileName, executeElement, "macro");
815                            }
816    
817                            for (Attribute attribute : attributes) {
818                                    String attributeName = attribute.getName();
819    
820                                    if (!attributeName.equals("macro") &&
821                                            !attributeName.equals("line-number")) {
822    
823                                            throwValidationException(
824                                                    1005, fileName, executeElement, attributeName);
825                                    }
826                            }
827                    }
828                    else if (selenium != null) {
829                            if (Validator.isNull(selenium) ||
830                                    !selenium.matches(allowedExecuteAttributeValuesRegex)) {
831    
832                                    throwValidationException(
833                                            1006, fileName, executeElement, "selenium");
834                            }
835    
836                            for (Attribute attribute : attributes) {
837                                    String attributeName = attribute.getName();
838    
839                                    if (!attributeName.equals("argument1") &&
840                                            !attributeName.equals("argument2") &&
841                                            !attributeName.equals("line-number") &&
842                                            !attributeName.equals("selenium")) {
843    
844                                            throwValidationException(
845                                                    1005, fileName, executeElement, attributeName);
846                                    }
847                            }
848                    }
849                    else if (testCase != null) {
850                            if (Validator.isNull(testCase) ||
851                                    !testCase.matches(allowedExecuteAttributeValuesRegex)) {
852    
853                                    throwValidationException(
854                                            1006, fileName, executeElement, "test-case");
855                            }
856    
857                            for (Attribute attribute : attributes) {
858                                    String attributeName = attribute.getName();
859    
860                                    if (!attributeName.equals("line-number") &&
861                                            !attributeName.equals("test-case")) {
862    
863                                            throwValidationException(
864                                                    1005, fileName, executeElement, attributeName);
865                                    }
866                            }
867                    }
868                    else if (testSuite != null) {
869                            if (Validator.isNull(testSuite) ||
870                                    !testSuite.matches(allowedExecuteAttributeValuesRegex)) {
871    
872                                    throwValidationException(
873                                            1006, fileName, executeElement, "test-suite");
874                            }
875    
876                            for (Attribute attribute : attributes) {
877                                    String attributeName = attribute.getName();
878    
879                                    if (!attributeName.equals("line-number") &&
880                                            !attributeName.equals("test-suite")) {
881    
882                                            throwValidationException(
883                                                    1005, fileName, executeElement, attributeName);
884                                    }
885                            }
886                    }
887                    else {
888                            throwValidationException(0, fileName);
889                    }
890    
891                    List<Element> elements = executeElement.elements();
892    
893                    if (allowedExecuteChildElementNames.length == 0) {
894                            if (!elements.isEmpty()) {
895                                    Element element = elements.get(0);
896    
897                                    String elementName = element.getName();
898    
899                                    throwValidationException(1002, fileName, element, elementName);
900                            }
901                    }
902                    else {
903                            String executeElementName = executeElement.getName();
904    
905                            for (Element element : elements) {
906                                    String elementName = element.getName();
907    
908                                    if (executeElementName.equals("condition")) {
909                                            throwValidationException(
910                                                    1002, fileName, element, elementName);
911                                    }
912    
913                                    if (elementName.equals("var")) {
914                                            validateSimpleElement(
915                                                    fileName, element, new String[] {"name", "value"});
916                                    }
917                                    else {
918                                            throwValidationException(
919                                                    1002, fileName, element, elementName);
920                                    }
921                            }
922                    }
923            }
924    
925            protected void validateFunctionDocument(
926                    String fileName, Element rootElement) {
927    
928                    if (!Validator.equals(rootElement.getName(), "definition")) {
929                            throwValidationException(1000, fileName, rootElement);
930                    }
931    
932                    List<Element> elements = rootElement.elements();
933    
934                    if (elements.isEmpty()) {
935                            throwValidationException(
936                                    1001, fileName, rootElement, new String[] {"command"});
937                    }
938    
939                    for (Element element : elements) {
940                            String elementName = element.getName();
941    
942                            if (elementName.equals("command")) {
943                                    String attributeValue = element.attributeValue("name");
944    
945                                    if (attributeValue == null) {
946                                            throwValidationException(1003, fileName, element, "name");
947                                    }
948                                    else if (Validator.isNull(attributeValue)) {
949                                            throwValidationException(1006, fileName, element, "name");
950                                    }
951    
952                                    validateBlockElement(
953                                            fileName, element, new String[] {"execute", "if"},
954                                            new String[] {"function", "selenium"}, new String[0],
955                                            new String[] {"condition"});
956                            }
957                            else {
958                                    throwValidationException(1002, fileName, element, elementName);
959                            }
960                    }
961            }
962    
963            protected void validateIfElement(
964                    String fileName, Element ifElement,
965                    String[] allowedBlockChildElementNames,
966                    String[] allowedExecuteAttributeNames,
967                    String[] allowedExecuteChildElementNames,
968                    String[] allowedIfConditionElementNames) {
969    
970                    List<Element> elements = ifElement.elements();
971    
972                    Set<String> elementNames = new HashSet<String>();
973    
974                    boolean hasAllowedIfConditionElementNames = false;
975    
976                    for (Element element : elements) {
977                            String elementName = element.getName();
978    
979                            elementNames.add(elementName);
980    
981                            if (ArrayUtil.contains(
982                                            allowedIfConditionElementNames, elementName)) {
983    
984                                    hasAllowedIfConditionElementNames = true;
985                            }
986    
987                            if (elementName.equals("condition")) {
988                                    validateExecuteElement(
989                                            fileName, element, allowedExecuteAttributeNames,
990                                            ".*(is|Is).+", allowedExecuteChildElementNames);
991                            }
992                            else if (elementName.equals("contains")) {
993                                    validateSimpleElement(
994                                            fileName, element, new String[] {"string", "substring"});
995                            }
996                            else if (elementName.equals("else") || elementName.equals("then")) {
997                                    validateBlockElement(
998                                            fileName, element, allowedBlockChildElementNames,
999                                            allowedExecuteAttributeNames,
1000                                            allowedExecuteChildElementNames,
1001                                            allowedIfConditionElementNames);
1002                            }
1003                            else if (elementName.equals("elseif")) {
1004                                    validateIfElement(
1005                                            fileName, element, allowedBlockChildElementNames,
1006                                            allowedExecuteAttributeNames,
1007                                            allowedExecuteChildElementNames,
1008                                            allowedIfConditionElementNames);
1009                            }
1010                            else if (elementName.equals("equals")) {
1011                                    validateSimpleElement(
1012                                            fileName, element, new String[] {"arg1", "arg2"});
1013                            }
1014                            else if (elementName.equals("isset")) {
1015                                    validateSimpleElement(fileName, element, new String[] {"var"});
1016                            }
1017                            else {
1018                                    throwValidationException(1002, fileName, element, elementName);
1019                            }
1020                    }
1021    
1022                    if (!hasAllowedIfConditionElementNames) {
1023                            throwValidationException(
1024                                    1001, fileName, ifElement, allowedIfConditionElementNames);
1025                    }
1026    
1027                    if (!elementNames.contains("then")) {
1028                            throwValidationException(
1029                                    1001, fileName, ifElement, new String[] {"then"});
1030                    }
1031            }
1032    
1033            protected void validateMacroDocument(String fileName, Element rootElement) {
1034                    if (!Validator.equals(rootElement.getName(), "definition")) {
1035                            throwValidationException(1000, fileName, rootElement);
1036                    }
1037    
1038                    List<Element> elements = rootElement.elements();
1039    
1040                    if (elements.isEmpty()) {
1041                            throwValidationException(
1042                                    1001, fileName, rootElement, new String[] {"command", "var"});
1043                    }
1044    
1045                    for (Element element : elements) {
1046                            String elementName = element.getName();
1047    
1048                            if (elementName.equals("command")) {
1049                                    String attributeValue = element.attributeValue("name");
1050    
1051                                    if (attributeValue == null) {
1052                                            throwValidationException(1003, fileName, element, "name");
1053                                    }
1054                                    else if (Validator.isNull(attributeValue)) {
1055                                            throwValidationException(1006, fileName, element, "name");
1056                                    }
1057    
1058                                    validateBlockElement(
1059                                            fileName, element,
1060                                            new String[] {
1061                                                    "echo", "execute", "fail", "if", "var","while"
1062                                            },
1063                                            new String[] {"action", "macro"}, new String[] {"var"},
1064                                            new String[] {"condition", "contains", "equals", "isset"});
1065                            }
1066                            else if (elementName.equals("var")) {
1067                                    validateSimpleElement(
1068                                            fileName, element, new String[] {"name", "value"});
1069                            }
1070                            else {
1071                                    throwValidationException(1002, fileName, element, elementName);
1072                            }
1073                    }
1074            }
1075    
1076            protected void validatePathDocument(String fileName, Element rootElement) {
1077                    Element headElement = rootElement.element("head");
1078    
1079                    Element titleElement = headElement.element("title");
1080    
1081                    String title = titleElement.getText();
1082    
1083                    int x = fileName.lastIndexOf(StringPool.SLASH);
1084                    int y = fileName.lastIndexOf(CharPool.PERIOD);
1085    
1086                    String shortFileName = fileName.substring(x + 1, y);
1087    
1088                    if ((title == null) || !shortFileName.equals(title)) {
1089                            throwValidationException(0, fileName);
1090                    }
1091    
1092                    Element bodyElement = rootElement.element("body");
1093    
1094                    Element tableElement = bodyElement.element("table");
1095    
1096                    Element theadElement = tableElement.element("thead");
1097    
1098                    Element trElement = theadElement.element("tr");
1099    
1100                    Element tdElement = trElement.element("td");
1101    
1102                    String tdText = tdElement.getText();
1103    
1104                    if ((tdText == null) || !shortFileName.equals(tdText)) {
1105                            throwValidationException(0, fileName);
1106                    }
1107    
1108                    Element tbodyElement = tableElement.element("tbody");
1109    
1110                    List<Element> elements = tbodyElement.elements();
1111    
1112                    for (Element element : elements) {
1113                            String elementName = element.getName();
1114    
1115                            if (elementName.equals("tr")) {
1116                                    validatePathTrElement(fileName, element);
1117                            }
1118                            else {
1119                                    throwValidationException(1002, fileName, element, elementName);
1120                            }
1121                    }
1122            }
1123    
1124            protected void validatePathTrElement(String fileName, Element trElement) {
1125                    List<Element> elements = trElement.elements();
1126    
1127                    for (Element element : elements) {
1128                            String elementName = element.getName();
1129    
1130                            if (!elementName.equals("td")) {
1131                                    throwValidationException(1002, fileName, element, elementName);
1132                            }
1133                    }
1134    
1135                    if (elements.size() < 3) {
1136                            throwValidationException(
1137                                    1001, fileName, trElement, new String[] {"td"});
1138                    }
1139    
1140                    if (elements.size() > 3) {
1141                            Element element = elements.get(3);
1142    
1143                            String elementName = element.getName();
1144    
1145                            throwValidationException(1002, fileName, element, elementName);
1146                    }
1147            }
1148    
1149            protected void validateSimpleElement(
1150                    String fileName, Element element, String[] neededAttributes) {
1151    
1152                    Map<String, Boolean> hasNeededAttributes =
1153                            new HashMap<String, Boolean>();
1154    
1155                    for (String neededAttribute : neededAttributes) {
1156                            hasNeededAttributes.put(neededAttribute, false);
1157                    }
1158    
1159                    List<Attribute> attributes = element.attributes();
1160    
1161                    for (Attribute attribute : attributes) {
1162                            String attributeName = attribute.getName();
1163                            String attributeValue = attribute.getValue();
1164    
1165                            if (Validator.isNull(attributeValue)) {
1166                                    throwValidationException(
1167                                            1006, fileName, element, attributeName);
1168                            }
1169    
1170                            if (hasNeededAttributes.containsKey(attributeName)) {
1171                                    hasNeededAttributes.put(attributeName, true);
1172                            }
1173    
1174                            if (!attributeName.equals("line-number") &&
1175                                    !hasNeededAttributes.containsKey(attributeName)) {
1176    
1177                                    throwValidationException(
1178                                            1005, fileName, element, attributeName);
1179                            }
1180                    }
1181    
1182                    for (String neededAttribute : neededAttributes) {
1183                            if (!hasNeededAttributes.get(neededAttribute)) {
1184                                    throwValidationException(
1185                                            1004, fileName, element, neededAttributes);
1186                            }
1187                    }
1188    
1189                    List<Element> childElements = element.elements();
1190    
1191                    if (!childElements.isEmpty()) {
1192                            Element childElement = childElements.get(0);
1193    
1194                            String childElementName = childElement.getName();
1195    
1196                            throwValidationException(
1197                                    1002, fileName, childElement, childElementName);
1198                    }
1199            }
1200    
1201            protected void validateTestCaseDocument(
1202                    String fileName, Element rootElement) {
1203    
1204                    if (!Validator.equals(rootElement.getName(), "definition")) {
1205                            throwValidationException(1000, fileName, rootElement);
1206                    }
1207    
1208                    List<Element> elements = rootElement.elements();
1209    
1210                    if (elements.isEmpty()) {
1211                            throwValidationException(
1212                                    1001, fileName, rootElement, new String[] {"command"});
1213                    }
1214    
1215                    for (Element element : elements) {
1216                            String elementName = element.getName();
1217    
1218                            if (elementName.equals("command")) {
1219                                    String attributeValue = element.attributeValue("name");
1220    
1221                                    if (attributeValue == null) {
1222                                            throwValidationException(1003, fileName, element, "name");
1223                                    }
1224                                    else if (Validator.isNull(attributeValue)) {
1225                                            throwValidationException(1006, fileName, element, "name");
1226                                    }
1227    
1228                                    validateBlockElement(
1229                                            fileName, element, new String[] {"execute", "var"},
1230                                            new String[] {"action", "macro"}, new String[] {"var"},
1231                                            new String[0]);
1232                            }
1233                            else if (elementName.equals("set-up") ||
1234                                             elementName.equals("tear-down")) {
1235    
1236                                    List<Attribute> attributes = element.attributes();
1237    
1238                                    for (Attribute attribute : attributes) {
1239                                            String attributeName = attribute.getName();
1240    
1241                                            if (!attributeName.equals("line-number")) {
1242                                                    throwValidationException(
1243                                                            1005, fileName, element, attributeName);
1244                                            }
1245                                    }
1246    
1247                                    validateBlockElement(
1248                                            fileName, element, new String[] {"execute", "var"},
1249                                            new String[] {"action", "macro"}, new String[] {"var"},
1250                                            new String[0]);
1251                            }
1252                            else if (elementName.equals("var")) {
1253                                    validateSimpleElement(
1254                                            fileName, element, new String[] {"name", "value"});
1255                            }
1256                            else {
1257                                    throwValidationException(1002, fileName, element, elementName);
1258                            }
1259                    }
1260            }
1261    
1262            protected void validateTestSuiteDocument(
1263                    String fileName, Element rootElement) {
1264    
1265                    if (!Validator.equals(rootElement.getName(), "definition")) {
1266                            throwValidationException(1000, fileName, rootElement);
1267                    }
1268    
1269                    List<Element> elements = rootElement.elements();
1270    
1271                    if (elements.isEmpty()) {
1272                            throwValidationException(
1273                                    1001, fileName, rootElement, new String[] {"execute"});
1274                    }
1275    
1276                    for (Element element : elements) {
1277                            String elementName = element.getName();
1278    
1279                            if (elementName.equals("execute")) {
1280                                    validateExecuteElement(
1281                                            fileName, element, new String[] {"test-case", "test-suite"},
1282                                            ".+", new String[0]);
1283                            }
1284                            else {
1285                                    throwValidationException(1002, fileName, element, elementName);
1286                            }
1287                    }
1288            }
1289    
1290            protected void validateWhileElement(
1291                    String fileName, Element whileElement,
1292                    String[] allowedBlockChildElementNames,
1293                    String[] allowedExecuteAttributeNames,
1294                    String[] allowedExecuteChildElementNames,
1295                    String[] allowedIfConditionElementNames) {
1296    
1297                    List<Element> elements = whileElement.elements();
1298    
1299                    Set<String> elementNames = new HashSet<String>();
1300    
1301                    for (Element element : elements) {
1302                            String elementName = element.getName();
1303    
1304                            elementNames.add(elementName);
1305    
1306                            if (elementName.equals("condition")) {
1307                                    validateExecuteElement(
1308                                            fileName, element, allowedExecuteAttributeNames,
1309                                            ".*(is|Is).+", allowedExecuteChildElementNames);
1310                            }
1311                            else if (elementName.equals("then")) {
1312                                    validateBlockElement(
1313                                            fileName, element, allowedBlockChildElementNames,
1314                                            allowedExecuteAttributeNames,
1315                                            allowedExecuteChildElementNames,
1316                                            allowedIfConditionElementNames);
1317                            }
1318                            else {
1319                                    throwValidationException(1002, fileName, element, elementName);
1320                            }
1321                    }
1322    
1323                    if (!elementNames.contains("condition") ||
1324                            !elementNames.contains("then")) {
1325    
1326                            throwValidationException(
1327                                    1001, fileName, whileElement,
1328                                    new String[] {"condition", "then"});
1329                    }
1330            }
1331    
1332            private static final String _TPL_ROOT =
1333                    "com/liferay/portal/tools/seleniumbuilder/dependencies/";
1334    
1335            private String _baseDir;
1336    
1337    }