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.collections.iterators.SingletonIterator;
021    import org.apache.myfaces.tobago.TobagoConstants;
022    
023    import javax.faces.application.FacesMessage;
024    import javax.faces.context.FacesContext;
025    import javax.faces.el.ValueBinding;
026    import java.util.ArrayList;
027    import java.util.Collections;
028    import java.util.Comparator;
029    import java.util.Iterator;
030    import java.util.List;
031    
032    public class UIMessages extends javax.faces.component.UIMessages {
033    
034      public static final String COMPONENT_TYPE = "org.apache.myfaces.tobago.Messages";
035    
036      private FacesMessage.Severity minSeverity;
037      private FacesMessage.Severity maxSeverity;
038      private Integer maxNumber;
039      private OrderBy orderBy;
040      private String forValue;
041      private Boolean confirmation;
042    
043      public List<Item> createMessageList(FacesContext facesContext) {
044    
045        List<Item> messages = createMessageListInternal(facesContext);
046    
047        // todo
048        if (OrderBy.SEVERITY.equals(orderBy)) {
049          // sort
050          Collections.sort(messages, new ItemComparator());
051        }
052        return messages;
053      }
054    
055      public int getMessageListCount(final FacesContext facesContext) {
056        return createMessageListInternal(facesContext).size();
057      }
058    
059      private List<Item> createMessageListInternal(FacesContext facesContext) {
060        Iterator clientIds;
061        if (isGlobalOnly()) {
062          clientIds = new SingletonIterator(null);
063        } else if (getFor() != null) {
064          clientIds = new SingletonIterator(getFor());
065        } else {
066          clientIds = facesContext.getClientIdsWithMessages();
067        }
068    
069        return collectMessageList(facesContext, clientIds);
070      }
071    
072      private List<Item> collectMessageList(FacesContext facesContext, Iterator clientIds) {
073        List<Item> messages = new ArrayList<Item>();
074        while(clientIds.hasNext()) {
075          String clientId = (String) clientIds.next();
076          Iterator<FacesMessage> i = facesContext.getMessages(clientId);
077          while (i.hasNext()) {
078            FacesMessage facesMessage = i.next();
079            if (maxNumber != null && messages.size() >= maxNumber) {
080              return messages;
081            }
082            if (facesMessage.getSeverity().getOrdinal() < getMinSeverity().getOrdinal()) {
083              continue;
084            }
085            if (facesMessage.getSeverity().getOrdinal() > getMaxSeverity().getOrdinal()) {
086              continue;
087            }
088            messages.add(new Item(clientId, facesMessage));
089          }
090        }
091        return messages;
092      }
093    
094      public static class Item {
095    
096        private String clientId;
097        private FacesMessage facesMessage;
098    
099        public Item(String clientId, FacesMessage facesMessage) {
100          this.clientId = clientId;
101          this.facesMessage = facesMessage;
102        }
103    
104        public String getClientId() {
105          return clientId;
106        }
107    
108        public void setClientId(String clientId) {
109          this.clientId = clientId;
110        }
111    
112        public FacesMessage getFacesMessage() {
113          return facesMessage;
114        }
115    
116        public void setFacesMessage(FacesMessage facesMessage) {
117          this.facesMessage = facesMessage;
118        }
119      }
120    
121      public static class ItemComparator implements Comparator<Item> {
122        public int compare(Item item1, Item item2) {
123          return item2.getFacesMessage().getSeverity().getOrdinal() - item1.getFacesMessage().getSeverity().getOrdinal();
124        }
125      }
126    
127      public FacesMessage.Severity getMinSeverity() {
128        if (minSeverity != null) {
129          return minSeverity;
130        }
131        ValueBinding vb = getValueBinding(TobagoConstants.ATTR_MIN_SEVERITY);
132        if (vb != null) {
133          return (FacesMessage.Severity) vb.getValue(getFacesContext());
134        } else {
135          return FacesMessage.SEVERITY_INFO;
136        }
137      }
138    
139      public void setMinSeverity(FacesMessage.Severity minSeverity) {
140        this.minSeverity = minSeverity;
141      }
142    
143      public FacesMessage.Severity getMaxSeverity() {
144        if (maxSeverity != null) {
145          return maxSeverity;
146        }
147        ValueBinding vb = getValueBinding(TobagoConstants.ATTR_MAX_SEVERITY);
148        if (vb != null) {
149          return (FacesMessage.Severity) vb.getValue(getFacesContext());
150        } else {
151          return FacesMessage.SEVERITY_FATAL;
152        }
153      }
154    
155      public void setMaxSeverity(FacesMessage.Severity maxSeverity) {
156        this.maxSeverity = maxSeverity;
157      }
158    
159      public Integer getMaxNumber() {
160        if (maxNumber != null) {
161          return maxNumber;
162        }
163        ValueBinding vb = getValueBinding(TobagoConstants.ATTR_MAX_NUMBER);
164        if (vb != null) {
165          Number number = (Number) vb.getValue(getFacesContext());
166          if (number != null) {
167            return Integer.valueOf(number.intValue());
168          }
169        }
170        return null;
171      }
172    
173      public void setMaxNumber(Integer maxNumber) {
174        this.maxNumber = maxNumber;
175      }
176    
177      public OrderBy getOrderBy() {
178        if (orderBy != null) {
179          return orderBy;
180        }
181        ValueBinding vb = getValueBinding(TobagoConstants.ATTR_ORDER_BY);
182        if (vb != null) {
183          return (OrderBy) vb.getValue(getFacesContext());
184        } else {
185          return OrderBy.OCCURENCE;
186        }
187      }
188    
189      public void setOrderBy(OrderBy orderBy) {
190        this.orderBy = orderBy;
191      }
192    
193      public void setFor(String forValue) {
194        this.forValue = forValue;
195      }
196    
197      public String getFor() {
198        if (forValue != null) {
199          return forValue;
200        }
201        ValueBinding vb = getValueBinding("for");
202        if (vb != null) {
203          return (String) vb.getValue(getFacesContext());
204        } else {
205          return null;
206        }
207      }
208    
209      public boolean isConfirmation() {
210        if (confirmation != null) {
211          return confirmation;
212        }
213        ValueBinding vb = getValueBinding(TobagoConstants.ATTR_CONFIRMATION);
214        if (vb != null) {
215          return (Boolean.TRUE.equals(vb.getValue(getFacesContext())));
216        } else {
217          return false;
218        }
219      }
220    
221      public void setConfirmation(boolean confirmation) {
222        this.confirmation = confirmation;
223      }
224    
225      @Override
226      public Object saveState(FacesContext context) {
227        Object[] values = new Object[7];
228        values[0] = super.saveState(context);
229        values[1] = minSeverity;
230        values[2] = maxSeverity;
231        values[3] = maxNumber;
232        values[4] = orderBy;
233        values[5] = forValue;
234        values[6] = confirmation;
235        return values;
236      }
237    
238      @Override
239      public void restoreState(FacesContext context, Object state) {
240        Object[] values = (Object[]) state;
241        super.restoreState(context, values[0]);
242        minSeverity = (FacesMessage.Severity) values[1];
243        maxSeverity = (FacesMessage.Severity) values[2];
244        maxNumber = (Integer) values[3];
245        orderBy = (OrderBy) values[4];
246        forValue = (String) values[5];
247        confirmation = (Boolean) values[6];
248      }
249    
250      public enum OrderBy {
251    
252        OCCURENCE,
253        SEVERITY;
254    
255        public static final String OCCURENCE_STRING = "occurence";
256        public static final String SEVERITY_STRING = "severity";
257    
258        public static OrderBy parse(String key) {
259          return valueOf(key.toUpperCase());
260        }
261    
262      }
263    }