1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.myfaces.trinidad.change;
20
21 import java.io.Serializable;
22
23 import java.util.Map;
24
25 import javax.el.ValueExpression;
26
27 import javax.faces.component.UIComponent;
28 import javax.faces.el.ValueBinding;
29
30 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
31
32
33 /**
34 * Change specialization for change in attributes.
35 * While applying this Change, the specified attribute state is restored.
36 * @version $Name: $ ($Revision: adfrt/faces/adf-faces-api/src/main/java/oracle/adf/view/faces/change/AttributeComponentChange.java#0 $) $Date: 10-nov-2005.19:09:56 $
37 */
38 public class AttributeComponentChange extends ComponentChange
39 {
40 /**
41 * Constructs an AttributeChange with the given attributeName and
42 * attributeValue.
43 * @param attributeName The name of the attribute for which the value needs
44 * to be restored.
45 * @param attributeValue The value of the attribute that needs to be restored.
46 * This value should be of type java.io.Serializable in order to be
47 * persisted. If the value is of type ValueExpression or ValueBinding,
48 * the component's ValueBinding or ValueExpression for the attribute
49 * will be updated and the current attribute value, if any, removed so
50 * that the new ValueExpression or ValueBinding can take precedence.
51 * @throws IllegalArgumentException if specified attributeName were to be null or
52 * the specified attributeValue isn't serializable
53 */
54 public AttributeComponentChange(
55 String attributeName,
56 Object attributeValue
57 )
58 {
59 if ((attributeName == null) || (attributeName.length() == 0))
60 throw new IllegalArgumentException(_LOG.getMessage(
61 "CANNOT_CONSTRUCT_ATTRIBUTECHANGE_WITH_NULL_NAME"));
62
63 if (attributeValue != null && !(attributeValue instanceof Serializable))
64 throw new IllegalArgumentException(_LOG.getMessage(
65 "UNSERIALIZABLE_VALUE", attributeValue));
66
67 _attributeName = attributeName;
68 _attributeValue = attributeValue;
69 }
70
71 /**
72 * Returns the name of the attribute that represents this Change.
73 */
74 public String getAttributeName()
75 {
76 return _attributeName;
77 }
78
79 /**
80 * Returns the value of the attribute corresponding to this AttributeChange.
81 */
82 public Object getAttributeValue()
83 {
84 return _attributeValue;
85 }
86
87 /**
88 * {@inheritDoc}
89 */
90 @Override
91 @SuppressWarnings("deprecation")
92 public void changeComponent(UIComponent uiComponent)
93 {
94 Map<String, Object> attributeMap = uiComponent.getAttributes();
95
96 // if the attributevalue is a ValueExpression or ValueBinding, use the
97 // appropriate setValueExpression/setValueBinding call and remove the
98 // current attribute value, if any, so that the ValueExpression/ValueBinding
99 // can take precedence
100 if (_attributeValue instanceof ValueExpression)
101 {
102 uiComponent.setValueExpression(_attributeName, (ValueExpression)_attributeValue);
103 attributeMap.remove(_attributeName);
104 }
105 else if (_attributeValue instanceof ValueBinding)
106 {
107 uiComponent.setValueBinding(_attributeName, (ValueBinding)_attributeValue);
108 attributeMap.remove(_attributeName);
109 }
110 else
111 {
112 attributeMap.put(_attributeName, _attributeValue);
113 }
114 }
115
116 @Override
117 public String toString()
118 {
119 return super.toString() + "[attribute=" + _attributeName +
120 ",value=" + _attributeValue + "]";
121 }
122
123 @Override
124 public int hashCode()
125 {
126 int hashCode = _attributeName.hashCode();
127
128 if (_attributeValue != null)
129 hashCode += 37 * _attributeValue.hashCode();
130
131 return hashCode;
132 }
133
134 @Override
135 public boolean equals(Object o)
136 {
137 if (o == this)
138 return true;
139
140 if (!(o instanceof AttributeComponentChange))
141 return false;
142
143 AttributeComponentChange other = (AttributeComponentChange)o;
144
145 return _attributeName.equals(other._attributeName) &&
146 ((_attributeValue == null)
147 ? other._attributeValue == null
148 : _attributeValue.equals(other._attributeValue));
149 }
150
151 private final String _attributeName;
152
153 //=-=pu: Should we disallow non-serializable values during construction itself
154 // and throw IllegalArgumentException ?
155 // Current known cases:
156 // The focusPath attribute of a tree, which is considered as a persistible
157 // Change takes a value that is a java.util.List. (-ve)
158 // treeState of a tree is a org.apache.myfaces.trinidad.model.PathSet that
159 // implements serializable. (+ve)
160 // selectionState of a table is org.apache.myfaces.trinidad.model.RowKeySet that
161 // implements externalizable. (+ve)
162 private final Object _attributeValue;
163 private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
164 AttributeComponentChange.class);
165 private static final long serialVersionUID = 1L;
166 }