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 }