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