• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

link-intersystems / lis-commons / #318

19 May 2024 07:18AM UTC coverage: 90.202% (-0.04%) from 90.246%
#318

push

renelink
Added generic index set and get methods to IndexedPropertyDesc.

16 of 25 new or added lines in 2 files covered. (64.0%)

4 existing lines in 2 files now uncovered.

7669 of 8502 relevant lines covered (90.2%)

0.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.92
/lis-commons-beans/src/main/java/com/link_intersystems/beans/java/JavaIndexedProperty.java
1
/**
2
 * Copyright 2011 Link Intersystems GmbH <rene.link@link-intersystems.com>
3
 * <p>
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 * <p>
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 * <p>
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.link_intersystems.beans.java;
17

18
import com.link_intersystems.beans.IndexedProperty;
19
import com.link_intersystems.beans.IndexedPropertyDesc;
20
import com.link_intersystems.beans.PropertyReadException;
21

22
import java.beans.IndexedPropertyDescriptor;
23
import java.lang.reflect.InvocationTargetException;
24
import java.lang.reflect.Method;
25
import java.util.Arrays;
26
import java.util.Objects;
27

28
/**
29
 * Provides access to an indexed java bean property.
30
 *
31
 * <pre>
32
 * public class SomeBean {
33
 *
34
 *    private String[] internalNames = new String[0];
35
 *
36
 *    public void setNames(String[] names){
37
 *      this.internalNames = names.clone();
38
 *    }
39
 *
40
 *    public String[] getNames(){
41
 *            return internalNames.clone();
42
 *    }
43
 *
44
 *    public void setNames(int index, String name){
45
 *      if(index >= internalNames.length){
46
 *              String[] newArr = new String[index];
47
 *              System.arraycopy(internalNames, 0, newArr, 0, internalNames.length);
48
 *          internalNames = newArr;
49
 *      }
50
 *      this.internalName[index] = name;
51
 *    }
52
 *
53
 *    public String getNames(int index){
54
 *            if(index >= internalNames.length){
55
 *         return null;
56
 *      }
57
 *            return internalNames[index];
58
 *    }
59
 *
60
 * }
61
 *
62
 * ...
63
 * SomeBean someBean = new SomeBean();
64
 *
65
 * Bean<SomeBean> bean = new Bean<SomeBean>(someBean);
66
 * IndexedProperty<String> namesProp = bean.getIndexedProperty("names");
67
 * namesProp.setValue(0, "Hello");
68
 * namesProp.setValue(1, "World");
69
 *
70
 * assertTrue(Arrays.equals(new String[]{"Hello", World}, someBean.getNames()));
71
 * assertTrue(Arrays.equals(new String[]{"Hello", World}, bean.getValue()));
72
 * </pre>
73
 *
74
 * @author René Link
75
 * <a href="mailto:rene.link@link-intersystems.com">[rene.link@link-
76
 * intersystems.com]</a>
77
 * @since 1.2.0;
78
 */
79
public class JavaIndexedProperty extends JavaProperty implements IndexedProperty {
80

81
    private static final long serialVersionUID = 3014890786938775513L;
82

83
    JavaIndexedProperty(JavaBean<?> bean, JavaIndexedPropertyDesc indexedPropertyDescriptor) {
84
        super(bean, indexedPropertyDescriptor);
1✔
85
    }
1✔
86

87
    @Override
88
    protected IndexedPropertyDescriptor getJavaPropertyDescriptor() {
UNCOV
89
        return (IndexedPropertyDescriptor) super.getJavaPropertyDescriptor();
×
90
    }
91

92
    @Override
93
    public IndexedPropertyDesc getPropertyDesc() {
94
        return (IndexedPropertyDesc) super.getPropertyDesc();
1✔
95
    }
96

97
    /**
98
     * Get the element value at the specified index of this
99
     * {@link JavaIndexedProperty}.
100
     *
101
     * @param index the index of the element to get.
102
     * @return the element value at the specified index of this
103
     * {@link JavaIndexedProperty}.
104
     * @since 1.2.0;
105
     */
106
    @Override
107
    @SuppressWarnings("unchecked")
108
    public <T> T getValue(int index) {
109
        IndexedPropertyDesc propertyDesc = getPropertyDesc();
1✔
110
        JavaBean<?> bean = getBean();
1✔
111
        return propertyDesc.getPropertyValue(bean.getBeanObject(), index);
1✔
112
    }
113

114
    /**
115
     * set the element value at the specified index of this
116
     * {@link JavaIndexedProperty}.
117
     *
118
     * @param index        the index of the element to set.
119
     * @param elementValue the element to set at the specified index.
120
     * @since 1.2.0;
121
     */
122
    @Override
123
    public void setValue(int index, Object elementValue) {
124
        IndexedPropertyDesc propertyDesc = getPropertyDesc();
1✔
125
        JavaBean<?> bean = getBean();
1✔
126
        propertyDesc.setPropertyValue(bean.getBeanObject(), index, elementValue);
1✔
127
    }
1✔
128

129
    /**
130
     * The Method that represents this {@link JavaIndexedProperty}'s index write
131
     * accessor (e.g. setPROPERTY(int index, TYPE value)).
132
     *
133
     * @return the Method that represents this {@link JavaIndexedProperty}'s index
134
     * write accessor (e.g. setPROPERTY(int index, TYPE value)) or
135
     * <code>null</code> if no write index method exists.
136
     * @since 1.2.0;
137
     */
138
    protected final Method getIndexedWriteMethod() {
UNCOV
139
        return getJavaPropertyDescriptor().getIndexedWriteMethod();
×
140
    }
141

142
    /**
143
     * The Method that represents this {@link JavaIndexedProperty}'s index read
144
     * accessor (e.g. TYPE getPROPERTY(int index)).
145
     *
146
     * @return the Method that represents this {@link JavaIndexedProperty}'s index
147
     * read accessor (e.g. TYPE getPROPERTY(int index)) or
148
     * <code>null</code> if no read index method exists.
149
     * @since 1.2.0;
150
     */
151
    protected final Method getIndexedReadMethod() {
UNCOV
152
        return getJavaPropertyDescriptor().getIndexedReadMethod();
×
153
    }
154

155
    /**
156
     * The name of this property + "[]" to indicate that it is an indexed
157
     * property.
158
     */
159
    @Override
160
    public String toString() {
161
        return super.getName() + "[]";
×
162
    }
163

164
    @Override
165
    public int hashCode() {
166
        if (isReadable()) {
1✔
167
            return hashCodeByArray();
1✔
168
        } else {
169
            return hashCodeByIndex();
1✔
170
        }
171
    }
172

173
    private int hashCodeByArray() {
174
        Object[] value = getValue();
1✔
175
        return Arrays.hashCode(value);
1✔
176
    }
177

178
    private int hashCodeByIndex() {
179
        final int prime = 31;
1✔
180
        int result = 1;
1✔
181

182
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
1✔
183
            try {
184
                Object value = getValue(i);
1✔
185
                result = prime * result + (value == null ? 0 : value.hashCode());
1✔
186
            } catch (PropertyReadException e) {
1✔
187
                Throwable cause = e.getCause();
1✔
188
                if (cause instanceof IndexOutOfBoundsException) {
1✔
189
                    break;
1✔
190
                } else {
191
                    throw new RuntimeException(e);
×
192
                }
193
            }
1✔
194
        }
195

196
        return result;
1✔
197
    }
198

199
    @Override
200
    public boolean equals(Object obj) {
201
        if (this == obj)
1✔
202
            return true;
1✔
203
        if (obj == null)
1✔
204
            return false;
1✔
205
        if (getClass() != obj.getClass())
1✔
206
            return false;
1✔
207
        IndexedProperty other = (IndexedProperty) obj;
1✔
208

209
        IndexedPropertyDesc propertyDescriptor = getPropertyDesc();
1✔
210
        IndexedPropertyDesc otherPropertyDescriptor = other.getPropertyDesc();
1✔
211

212
        if (!propertyDescriptor.equals(otherPropertyDescriptor)) {
1✔
213
            return false;
×
214
        }
215

216
        if (isReadable()) {
1✔
217
            return equalsByArray(other);
1✔
218
        } else {
219
            return equalsByIndex(other);
1✔
220
        }
221
    }
222

223
    private boolean equalsByArray(IndexedProperty other) {
224
        if (!other.getPropertyDesc().isReadable()) {
1✔
225
            return false;
×
226
        }
227

228
        Object[] value = getValue();
1✔
229
        Object[] otherValue = other.getValue();
1✔
230

231
        return Arrays.equals(value, otherValue);
1✔
232
    }
233

234
    private boolean equalsByIndex(IndexedProperty other) {
235
        boolean equal = true;
1✔
236

237
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
1✔
238
            try {
239
                Object value = getValue(i);
1✔
240

241
                try {
242
                    Object otherValue = other.getValue(i);
1✔
243

244
                    equal = Objects.equals(value, otherValue);
1✔
245
                    if (!equal) {
1✔
246
                        break;
1✔
247
                    }
248
                } catch (PropertyReadException e) {
×
249
                    equal = false;
×
250
                    Throwable cause = e.getCause();
×
251
                    if (cause instanceof IndexOutOfBoundsException) {
×
252
                        break;
×
253
                    } else {
254
                        throw new RuntimeException(e);
×
255
                    }
256
                }
1✔
257

258
            } catch (PropertyReadException e) {
1✔
259
                try {
260
                    other.getValue(i);
×
261
                    equal = false;
×
262
                } catch (PropertyReadException pe) {
1✔
263
                    Throwable cause = pe.getCause();
1✔
264
                    if (!(cause instanceof IndexOutOfBoundsException)) {
1✔
265
                        throw new RuntimeException(e);
×
266
                    }
267
                }
×
268

269
                Throwable cause = e.getCause();
1✔
270
                if (cause instanceof IndexOutOfBoundsException) {
1✔
271
                    break;
1✔
272
                } else {
273
                    throw new RuntimeException(e);
×
274
                }
275
            }
1✔
276

277
        }
278

279
        return equal;
1✔
280
    }
281

282
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc