Use properly-compiled Pattern
[mdsal.git] / binding2 / mdsal-binding2-generator-util / src / main / java / org / opendaylight / mdsal / binding / javav2 / generator / util / YangSnippetCleaner.java
1 /*
2  * Copyright (c) 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.binding.javav2.generator.util;
9
10 import com.google.common.annotations.Beta;
11 import java.util.regex.Pattern;
12 import javax.annotation.RegEx;
13 import org.apache.commons.lang3.StringUtils;
14
15 /**
16  * Utility class for cleaning yang models of excess whitespaces
17  */
18 @Beta
19 public final class YangSnippetCleaner {
20
21     private static final String[] RESERVED_LINES = { "yang-version", "namespace" };
22
23     @RegEx
24     private static final String NEW_LINE_REGEX = "\\r?\\n";
25     private static final Pattern NEW_LINE_PATTERN = Pattern.compile(NEW_LINE_REGEX);
26
27     @RegEx
28     private static final String WS_REGEX = "\\s+";
29     private static final Pattern WS_PATTERN = Pattern.compile(WS_REGEX);
30
31     private static final String START_BODY = "{";
32     private static final String END_BODY = "}";
33     private static final String KEY_PART = "key \"";
34     private static final String UNIQUE_PART = "unique \"";
35     private static final String SPECIAL_END_LINE = "\";";
36
37     private static final char NEW_LINE = '\n';
38     private static final char SPACE = ' ';
39
40     private static final int INDENT = 4;
41
42     private YangSnippetCleaner() {
43         throw new UnsupportedOperationException("Util class");
44     }
45
46     /**
47      * Cleaning yang model of excess whitespaces, adding indentations
48      *
49      * @param unformedYang
50      *            - unformed yang model
51      * @return cleaned yang model
52      */
53     public static String clean(final String unformedYang) {
54         int indentCount = 0;
55         final StringBuilder sb = new StringBuilder();
56         final String[] splitter = NEW_LINE_PATTERN.split(unformedYang);
57
58         for (int i = 0; i < splitter.length; i++) {
59             if (!StringUtils.isBlank(splitter[i])) {
60                 String line = cleanLine(splitter[i]);
61                 if (START_BODY.equals(line)) {
62                     indentCount = mergeWithPrevious(sb, indentCount);
63                     continue;
64                 }
65                 if ((line.contains(KEY_PART) || line.contains(UNIQUE_PART)) && line.endsWith(SPECIAL_END_LINE)) {
66                     line = new StringBuilder(line.substring(0, line.indexOf(SPECIAL_END_LINE) - 1))
67                             .append(SPECIAL_END_LINE).toString();
68                 }
69                 indentCount = lineIndent(sb, indentCount, line);
70                 sb.append(line).append(NEW_LINE);
71                 if (!StringUtils.startsWithAny(line, RESERVED_LINES) && indentCount == 1 && i != 0) {
72                         sb.append(NEW_LINE);
73                 }
74             }
75         }
76         if (sb.length() == 0) {
77             return "";
78         }
79         if (sb.charAt(sb.length() - 4) == NEW_LINE && sb.charAt(sb.length() - 3) == NEW_LINE) {
80             sb.deleteCharAt(sb.length() - 3);
81         }
82         removeRemainingWhitespace(sb);
83         sb.append(NEW_LINE);
84
85         return sb.toString();
86     }
87
88     private static int mergeWithPrevious(final StringBuilder sb, final int indentCount) {
89         int newIndentCount = indentCount;
90         removeRemainingWhitespace(sb);
91         sb.append(SPACE);
92         sb.append(START_BODY);
93         sb.append(NEW_LINE);
94         return ++newIndentCount;
95     }
96
97     private static void removeRemainingWhitespace(final StringBuilder sb) {
98         while (StringUtils.isWhitespace(String.valueOf(sb.charAt(sb.length() - 1)))) {
99             sb.deleteCharAt(sb.length() - 1);
100         }
101     }
102
103     private static String cleanLine(final String split) {
104         final StringBuilder sb = new StringBuilder();
105         final String[] s = WS_PATTERN.split(split);
106         for (int i = 0; i < s.length; i++) {
107             if (!StringUtils.isBlank(s[i])) {
108                 sb.append(s[i]);
109                 if (i != s.length - 1) {
110                     sb.append(SPACE);
111                 }
112             }
113         }
114         return sb.toString();
115     }
116
117     private static int lineIndent(final StringBuilder sb, final int indentCount, final String line) {
118         int newIndentCount = indentCount;
119         if (line.contains(END_BODY) && !line.contains(START_BODY)) {
120             newIndentCount--;
121         }
122         for (int i = 0; i < newIndentCount * INDENT; i++) {
123             sb.append(SPACE);
124         }
125
126         if (line.contains(START_BODY) && !line.contains(END_BODY)) {
127             newIndentCount++;
128         }
129
130         return newIndentCount;
131     }
132 }