001    package org.apache.myfaces.tobago.component;
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.logging.Log;
021    import org.apache.commons.logging.LogFactory;
022    import org.apache.commons.lang.math.NumberUtils;
023    
024    import java.util.StringTokenizer;
025    import java.util.List;
026    import java.util.ArrayList;
027    
028    /*
029     * Date: May 2, 2007
030     * Time: 1:11:25 PM
031     */
032    public class LayoutTokens {
033    
034      private static final Log LOG = LogFactory.getLog(LayoutTokens.class);
035    
036      private List<LayoutToken> tokens = new ArrayList<LayoutToken>();
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 static LayoutTokens parse(String[] tokens) {
071        LayoutTokens layoutTokens = new LayoutTokens();
072        for (String token : tokens) {
073          parseToken(token, layoutTokens);
074        }
075        return layoutTokens;
076      }
077    
078      public static LayoutTokens parse(String tokens) {
079        return parse(tokens, null);
080      }
081    
082      public static LayoutTokens parse(String tokens, LayoutToken defaultToken) {
083        LayoutTokens layoutTokens = new LayoutTokens();
084        if (tokens == null) {
085          layoutTokens.addToken(defaultToken);
086          return layoutTokens;
087        }
088        StringTokenizer tokenizer = new StringTokenizer(tokens, ";");
089    
090        while (tokenizer.hasMoreTokens()) {
091          String token = tokenizer.nextToken().trim();
092          parseToken(token, layoutTokens);
093        }
094        return layoutTokens;
095      }
096    
097      private static void parseToken(String token, LayoutTokens layoutTokens) {
098        LayoutToken layoutToken = parseToken(token);
099        if (layoutToken != null) {
100          layoutTokens.addToken(layoutToken);
101        }
102      }
103    
104      public static LayoutToken parseToken(String token) {
105        try {
106          if ("*".equals(token)) {
107            return RelativeLayoutToken.DEFAULT_INSTANCE;
108          } else if (token.equals("fixed")) {
109            return FixedLayoutToken.INSTANCE;
110          } else if (token.equals("minimum")) {
111            return new MinimumLayoutToken();
112          } else if (isPixelToken(token)) {
113            return new PixelLayoutToken(Integer.parseInt(removeSuffix(token, PixelLayoutToken.SUFFIX)));
114          } else if (isPercentToken(token)) {
115            return new PercentLayoutToken(Integer.parseInt(removeSuffix(token, PercentLayoutToken.SUFFIX)));
116          } else if (isRelativeToken(token)) {
117            return new RelativeLayoutToken(Integer.parseInt(removeSuffix(token, RelativeLayoutToken.SUFFIX)));
118          } else {
119            LOG.error("Ignoring unknown layout token '" + token + "'");
120          }
121        } catch (NumberFormatException e) {
122          LOG.error("Error parsing layout token '" + token + "'", e);
123        }
124        return null;
125      }
126    
127      static boolean isPixelToken(String token) {
128        return isNumberAndSuffix(token, PixelLayoutToken.SUFFIX);
129      }
130    
131      static boolean isPercentToken(String token) {
132        return isNumberAndSuffix(token, PercentLayoutToken.SUFFIX);
133      }
134    
135      static boolean isRelativeToken(String token) {
136        return isNumberAndSuffix(token, RelativeLayoutToken.SUFFIX);
137      }
138    
139      static boolean isNumberAndSuffix(String token, String suffix) {
140        return token.endsWith(suffix)
141            && NumberUtils.isDigits(removeSuffix(token, suffix));
142      }
143    
144      private static String removeSuffix(String token, String suffix) {
145        return token.substring(0, token.length() - suffix.length());
146      }
147    
148      public String toString() {
149        StringBuilder str = new StringBuilder();
150        for (LayoutToken token : tokens) {
151          str.append(token);
152          str.append(";");
153        }
154        return str.toString();
155      }
156    
157    }
158