001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *   http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    package org.apache.myfaces.tobago.component;
021    
022    import org.apache.commons.collections.iterators.SingletonIterator;
023    import org.apache.myfaces.tobago.TobagoConstants;
024    import org.apache.myfaces.tobago.util.Deprecation;
025    
026    import javax.faces.application.FacesMessage;
027    import javax.faces.context.FacesContext;
028    import javax.faces.el.ValueBinding;
029    import java.util.ArrayList;
030    import java.util.Collections;
031    import java.util.Comparator;
032    import java.util.Iterator;
033    import java.util.List;
034    
035    public class UIMessages extends javax.faces.component.UIMessages {
036    
037      public static final String COMPONENT_TYPE = "org.apache.myfaces.tobago.Messages";
038    
039      private FacesMessage.Severity minSeverity;
040      private FacesMessage.Severity maxSeverity;
041      private Integer maxNumber;
042      private OrderBy orderBy;
043      private String forValue;
044      private Boolean confirmation;
045    
046      public List<Item> createMessageList(FacesContext facesContext) {
047    
048        List<Item> messages = createMessageListInternal(facesContext);
049    
050        // todo
051        if (OrderBy.SEVERITY.equals(orderBy)) {
052          // sort
053          Collections.sort(messages, new ItemComparator());
054        }
055        return messages;
056      }
057    
058      public int getMessageListCount(final FacesContext facesContext) {
059        return createMessageListInternal(facesContext).size();
060      }
061    
062      private List<Item> createMessageListInternal(FacesContext facesContext) {
063        Iterator clientIds;
064        if (isGlobalOnly()) {
065          clientIds = new SingletonIterator(null);
066        } else if (getFor() != null) {
067          clientIds = new SingletonIterator(getFor());
068        } else {
069          clientIds = facesContext.getClientIdsWithMessages();
070        }
071    
072        return collectMessageList(facesContext, clientIds);
073      }
074    
075      private List<Item> collectMessageList(FacesContext facesContext, Iterator clientIds) {
076        List<Item> messages = new ArrayList<Item>();
077        while(clientIds.hasNext()) {
078          String clientId = (String) clientIds.next();
079          Iterator<FacesMessage> i = facesContext.getMessages(clientId);
080          while (i.hasNext()) {
081            FacesMessage facesMessage = i.next();
082            if (maxNumber != null && messages.size() >= maxNumber) {
083              return messages;
084            }
085            if (facesMessage.getSeverity().getOrdinal() < getMinSeverity().getOrdinal()) {
086              continue;
087            }
088            if (facesMessage.getSeverity().getOrdinal() > getMaxSeverity().getOrdinal()) {
089              continue;
090            }
091            messages.add(new Item(clientId, facesMessage));
092          }
093        }
094        return messages;
095      }
096    
097      public static class Item {
098    
099        private String clientId;
100        private FacesMessage facesMessage;
101    
102        public Item(String clientId, FacesMessage facesMessage) {
103          this.clientId = clientId;
104          this.facesMessage = facesMessage;
105        }
106    
107        public String getClientId() {
108          return clientId;
109        }
110    
111        public void setClientId(String clientId) {
112          this.clientId = clientId;
113        }
114    
115        public FacesMessage getFacesMessage() {
116          return facesMessage;
117        }
118    
119        public void setFacesMessage(FacesMessage facesMessage) {
120          this.facesMessage = facesMessage;
121        }
122      }
123    
124      public static class ItemComparator implements Comparator<Item> {
125        public int compare(Item item1, Item item2) {
126          return item2.getFacesMessage().getSeverity().getOrdinal() - item1.getFacesMessage().getSeverity().getOrdinal();
127        }
128      }
129    
130      public FacesMessage.Severity getMinSeverity() {
131        if (minSeverity != null) {
132          return minSeverity;
133        }
134        ValueBinding vb = getValueBinding(TobagoConstants.ATTR_MIN_SEVERITY);
135        if (vb != null) {
136          return (FacesMessage.Severity) vb.getValue(getFacesContext());
137        } else {
138          return FacesMessage.SEVERITY_INFO;
139        }
140      }
141    
142      public void setMinSeverity(FacesMessage.Severity minSeverity) {
143        this.minSeverity = minSeverity;
144      }
145    
146      public FacesMessage.Severity getMaxSeverity() {
147        if (maxSeverity != null) {
148          return maxSeverity;
149        }
150        ValueBinding vb = getValueBinding(TobagoConstants.ATTR_MAX_SEVERITY);
151        if (vb != null) {
152          return (FacesMessage.Severity) vb.getValue(getFacesContext());
153        } else {
154          return FacesMessage.SEVERITY_FATAL;
155        }
156      }
157    
158      public void setMaxSeverity(FacesMessage.Severity maxSeverity) {
159        this.maxSeverity = maxSeverity;
160      }
161    
162      public Integer getMaxNumber() {
163        if (maxNumber != null) {
164          return maxNumber;
165        }
166        ValueBinding vb = getValueBinding(TobagoConstants.ATTR_MAX_NUMBER);
167        if (vb != null) {
168          Number number = (Number) vb.getValue(getFacesContext());
169          if (number != null) {
170            return Integer.valueOf(number.intValue());
171          }
172        }
173        return null;
174      }
175    
176      public void setMaxNumber(Integer maxNumber) {
177        this.maxNumber = maxNumber;
178      }
179    
180      public OrderBy getOrderBy() {
181        if (orderBy != null) {
182          return orderBy;
183        }
184        ValueBinding vb = getValueBinding(TobagoConstants.ATTR_ORDER_BY);
185        if (vb != null) {
186          return (OrderBy) vb.getValue(getFacesContext());
187        } else {
188          return OrderBy.OCCURENCE;
189        }
190      }
191    
192      public void setOrderBy(OrderBy orderBy) {
193        this.orderBy = orderBy;
194      }
195    
196      public void setFor(String forValue) {
197        this.forValue = forValue;
198      }
199    
200      public String getFor() {
201        if (forValue != null) {
202          return forValue;
203        }
204        ValueBinding vb = getValueBinding("for");
205        if (vb != null) {
206          return (String) vb.getValue(getFacesContext());
207        } else {
208          return null;
209        }
210      }
211    
212      public boolean isConfirmation() {
213        if (confirmation != null) {
214          return confirmation;
215        }
216        ValueBinding vb = getValueBinding(TobagoConstants.ATTR_CONFIRMATION);
217        if (vb != null) {
218          return (Boolean.TRUE.equals(vb.getValue(getFacesContext())));
219        } else {
220          return false;
221        }
222      }
223    
224      public void setConfirmation(boolean confirmation) {
225        this.confirmation = confirmation;
226      }
227    
228      @Override
229      public Object saveState(FacesContext context) {
230        Object[] values = new Object[7];
231        values[0] = super.saveState(context);
232        values[1] = minSeverity;
233        values[2] = maxSeverity;
234        values[3] = maxNumber;
235        values[4] = orderBy;
236        values[5] = forValue;
237        values[6] = confirmation;
238        return values;
239      }
240    
241      @Override
242      public void restoreState(FacesContext context, Object state) {
243        Object[] values = (Object[]) state;
244        super.restoreState(context, values[0]);
245        minSeverity = (FacesMessage.Severity) values[1];
246        maxSeverity = (FacesMessage.Severity) values[2];
247        maxNumber = (Integer) values[3];
248        orderBy = (OrderBy) values[4];
249        forValue = (String) values[5];
250        confirmation = (Boolean) values[6];
251      }
252    
253      public enum OrderBy {
254    
255        OCCURENCE,
256        SEVERITY;
257    
258        public static final String OCCURENCE_STRING = "occurence";
259        public static final String OCCURRENCE_STRING = "occurrence";
260        public static final String SEVERITY_STRING = "severity";
261    
262        public static OrderBy parse(String key) {
263          if (OCCURENCE_STRING.equals(key)) {
264            Deprecation.LOG.warn("Please use '" + OCCURRENCE_STRING + "' instead of '" + OCCURENCE_STRING + "'");
265          }
266          if (OCCURRENCE_STRING.equals(key)) {
267            key = OCCURENCE_STRING;
268          }
269          return valueOf(key.toUpperCase());
270        }
271    
272      }
273    }