001 package org.apache.myfaces.tobago.layout;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one or more
005 * contributor license agreements. See the NOTICE file distributed with
006 * this work for additional information regarding copyright ownership.
007 * The ASF licenses this file to You under the Apache License, Version 2.0
008 * (the "License"); you may not use this file except in compliance with
009 * the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020 import org.apache.commons.lang.math.NumberUtils;
021 import org.slf4j.Logger;
022 import org.slf4j.LoggerFactory;
023
024 import java.util.ArrayList;
025 import java.util.Iterator;
026 import java.util.List;
027 import java.util.StringTokenizer;
028
029 public final class LayoutTokens implements Iterable<LayoutToken> {
030
031 private static final Logger LOG = LoggerFactory.getLogger(LayoutTokens.class);
032
033 private List<LayoutToken> tokens = new ArrayList<LayoutToken>();
034
035 public LayoutTokens() {
036 }
037
038 public int getSize() {
039 return tokens.size();
040 }
041
042 public void set(int index, LayoutToken token) {
043 tokens.set(index, token);
044 }
045
046 public boolean isEmpty() {
047 return getSize() == 0;
048 }
049
050 public LayoutToken get(int index) {
051 return tokens.get(index);
052 }
053
054 public void shrinkSizeTo(int size) {
055 for (int i = getSize() - 1; i >= size; i--) {
056 tokens.remove(i);
057 }
058 }
059
060 public void ensureSize(int size, LayoutToken token) {
061 for (int index = getSize(); index < size; index++) {
062 addToken(token);
063 }
064 }
065
066 public void addToken(LayoutToken token) {
067 tokens.add(token);
068 }
069
070 public List<LayoutToken> getTokens() {
071 return tokens;
072 }
073
074 public Iterator<LayoutToken> iterator() {
075 return tokens.iterator();
076 }
077
078 public static LayoutTokens parse(String[] tokens) {
079 LayoutTokens layoutTokens = new LayoutTokens();
080 for (String token : tokens) {
081 parseToken(token, layoutTokens);
082 }
083 return layoutTokens;
084 }
085
086 public static LayoutTokens parse(String tokens) {
087 return parse(tokens, null);
088 }
089
090 public static LayoutTokens parse(String tokens, LayoutToken defaultToken) {
091 LayoutTokens layoutTokens = new LayoutTokens();
092 if (tokens == null) {
093 layoutTokens.addToken(defaultToken);
094 return layoutTokens;
095 }
096 StringTokenizer tokenizer = new StringTokenizer(tokens, ";");
097
098 while (tokenizer.hasMoreTokens()) {
099 String token = tokenizer.nextToken().trim();
100 parseToken(token, layoutTokens);
101 }
102 return layoutTokens;
103 }
104
105 private static void parseToken(String token, LayoutTokens layoutTokens) {
106 LayoutToken layoutToken = parseToken(token);
107 if (layoutToken != null) {
108 layoutTokens.addToken(layoutToken);
109 }
110 }
111
112 public static LayoutToken parseToken(String token) {
113 try {
114 if ("*".equals(token)) {
115 return RelativeLayoutToken.DEFAULT_INSTANCE;
116 } else if (token == null) {
117 LOG.error("Empty layout token! Using 'auto' instead.");
118 return AutoLayoutToken.INSTANCE;
119 } else if ("fixed".equals(token) || "auto".equals(token)) {
120 return AutoLayoutToken.INSTANCE;
121 } else if ("minimum".equals(token)) {
122 return new MinimumLayoutToken();
123 } else if (isPixelToken(token)) {
124 return new PixelLayoutToken(Integer.parseInt(removeSuffix(token, PixelLayoutToken.SUFFIX)));
125 } else if (isPercentToken(token)) {
126 return new PercentLayoutToken(Integer.parseInt(removeSuffix(token, PercentLayoutToken.SUFFIX)));
127 } else if (isRelativeToken(token)) {
128 return new RelativeLayoutToken(Integer.parseInt(removeSuffix(token, RelativeLayoutToken.SUFFIX)));
129 } else {
130 LOG.error("Unknown layout token '" + token + "'! Using 'auto' instead.");
131 return AutoLayoutToken.INSTANCE;
132 }
133 } catch (NumberFormatException e) {
134 LOG.error("Error parsing layout token '" + token + "'! Using 'auto' instead.");
135 return AutoLayoutToken.INSTANCE;
136 }
137 }
138
139 static boolean isPixelToken(String token) {
140 return isNumberAndSuffix(token, PixelLayoutToken.SUFFIX);
141 }
142
143 static boolean isPercentToken(String token) {
144 return isNumberAndSuffix(token, PercentLayoutToken.SUFFIX);
145 }
146
147 static boolean isRelativeToken(String token) {
148 return isNumberAndSuffix(token, RelativeLayoutToken.SUFFIX);
149 }
150
151 static boolean isNumberAndSuffix(String token, String suffix) {
152 return token.endsWith(suffix)
153 && NumberUtils.isDigits(removeSuffix(token, suffix));
154 }
155
156 private static String removeSuffix(String token, String suffix) {
157 return token.substring(0, token.length() - suffix.length());
158 }
159
160 public String toString() {
161 StringBuilder str = new StringBuilder();
162 for (LayoutToken token : tokens) {
163 str.append(token);
164 str.append(";");
165 }
166 return str.toString();
167 }
168
169 }