/** * Copyright (c) 2013-2016 Angelo ZERR. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation */ package tern.angular.modules; import java.util.ArrayList; import java.util.List; /** * Directive helper. * */ public class DirectiveHelper { public static final String ANY_TAG = "any"; public static final List<String> STARTS_WITH; public static final List<Character> DELIMITERS; static { STARTS_WITH = new ArrayList<String>(); STARTS_WITH.add(""); STARTS_WITH.add("x-"); STARTS_WITH.add("data-"); DELIMITERS = new ArrayList<Character>(); DELIMITERS.add(':'); // colon delimiter DELIMITERS.add('-'); // minus delimiter DELIMITERS.add('_'); // underscore delimiter } private DirectiveHelper() { } /** * * Angular normalizes an element's tag and attribute name to determine which * elements match which directives. We typically refer to directives by * their case-sensitive camelCase normalized name (e.g. ngModel). However, * since HTML is case-insensitive, we refer to directives in the DOM by * lower-case forms, typically using dash-delimited attributes on DOM * elements (e.g. ng-model). * * The normalization process is as follows: * * <ol> * <li>Strip x- and data- from the front of the element/attributes.</li> * <li>Convert the :, -, or _-delimited name to camelCase.</li> * </ol> * * See http://docs.angularjs.org/guide/directive * * @return */ public static String normalize(String name) { if (name == null) { return null; } // 1) Strip x- and data- from the front of the element/attributes int startIndex = 0; char[] chs = name.toCharArray(); int length = chs.length; if (length >= 2) { if (chs[0] == 'x' && chs[1] == '-') { // starts with x- startIndex = 2; } else { if (length >= 5) { // starts with data- if (chs[0] == 'd' && chs[1] == 'a' && chs[2] == 't' && chs[3] == 'a' && chs[4] == '-') { startIndex = 5; } } } } // 2) Convert the :, -, or _-delimited name to camelCase. StringBuilder normalizedName = new StringBuilder(); boolean delimiterFound = false; char c = 0; for (int i = startIndex; i < chs.length; i++) { c = chs[i]; if (delimiterFound) { normalizedName.append(Character.toUpperCase(c)); delimiterFound = false; } else { if (DELIMITERS.contains(c)) { delimiterFound = true; } else { normalizedName.append(c); } } } return normalizedName.toString(); } public static List<String> getDirectiveNames(String name) { List<String> tokensName = buildTokensName(name); List<String> names = new ArrayList<String>(); // ex ngBind int index = 0; names.add(name); StringBuilder s = null; for (Character delimiter : DirectiveHelper.DELIMITERS) { for (String startsWith : DirectiveHelper.STARTS_WITH) { s = new StringBuilder(startsWith); for (int i = 0; i < tokensName.size(); i++) { if (i > 0) { s.append(delimiter); } s.append(tokensName.get(i)); } names.add(s.toString()); } } return names; } private static List<String> buildTokensName(String name) { char[] chars = name.toCharArray(); List<String> tokens = new ArrayList<String>(); StringBuilder current = new StringBuilder(); char c = 0; for (int i = 0; i < chars.length; i++) { c = chars[i]; if (!Character.isUpperCase(c)) { current.append(c); } else { tokens.add(current.toString()); current.setLength(0); current.append(Character.toLowerCase(c)); } } if (current.length() > 0) { tokens.add(current.toString()); } return tokens; } public static boolean isSupport(IDirectiveSyntax syntax, int i) { if (syntax == null) { return true; } switch (i) { case 0: return syntax.isUseOriginalName(); case 1: return syntax.isColonDelimiter() && syntax.isStartsWithNothing(); case 2: return syntax.isColonDelimiter() && syntax.isStartsWithX(); case 3: return syntax.isColonDelimiter() && syntax.isStartsWithData(); case 4: return syntax.isMinusDelimiter() && syntax.isStartsWithNothing(); case 5: return syntax.isMinusDelimiter() && syntax.isStartsWithX(); case 6: return syntax.isMinusDelimiter() && syntax.isStartsWithData(); case 7: return syntax.isUnderscoreDelimiter() && syntax.isStartsWithNothing(); case 8: return syntax.isUnderscoreDelimiter() && syntax.isStartsWithX(); case 9: return syntax.isUnderscoreDelimiter() && syntax.isStartsWithData(); } return false; } }