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

link-intersystems / lis-commons / #222

24 Aug 2023 06:21AM UTC coverage: 89.966% (+0.08%) from 89.884%
#222

push

renelink
Extended property copy support.

91 of 91 new or added lines in 4 files covered. (100.0%)

7352 of 8172 relevant lines covered (89.97%)

0.9 hits per line

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

98.63
/lis-commons-beans/src/main/java/com/link_intersystems/beans/ExactPropertyCopyStrategy.java
1
package com.link_intersystems.beans;
2

3
import java.lang.reflect.Array;
4

5
import static java.util.Objects.*;
6

7
class ExactPropertyCopyStrategy implements PropertyCopyStrategy {
1✔
8

9
    private static interface IndexedPropertyIterator {
10

11
        public boolean next();
12

13
        public int getIndex();
14

15
        public Object getValue();
16

17
        Object toArray();
18
    }
19

20
    private static class OnTheFlyIndexPropertyIterator implements IndexedPropertyIterator {
21

22
        public static final int INCREASE_ARRAY_SIZE = 16;
23
        private int index = 0;
1✔
24
        private IndexedProperty indexedProperty;
25
        private Object value;
26

27

28
        public OnTheFlyIndexPropertyIterator(IndexedProperty indexedProperty) {
1✔
29
            this.indexedProperty = requireNonNull(indexedProperty);
1✔
30
        }
1✔
31

32
        @Override
33
        public boolean next() {
34
            try {
35
                value = indexedProperty.getValue(index++);
1✔
36
                return true;
1✔
37
            } catch (ArrayIndexOutOfBoundsException e) {
1✔
38
                return false;
1✔
39
            }
40
        }
41

42
        @Override
43
        public int getIndex() {
44
            return index - 1;
1✔
45
        }
46

47
        @Override
48
        public Object getValue() {
49
            return value;
1✔
50
        }
51

52
        @Override
53
        public Object toArray() {
54
            Class<?> type = indexedProperty.getPropertyDesc().getType();
1✔
55
            Object targetArray = Array.newInstance(type, INCREASE_ARRAY_SIZE);
1✔
56
            int i = 0;
1✔
57

58

59
            for (; i <= Integer.MAX_VALUE; i++) {
1✔
60
                try {
61
                    Object valueAtIndex = indexedProperty.getValue(i);
1✔
62
                    int targetArrayLength = Array.getLength(targetArray);
1✔
63
                    if (i >= targetArrayLength) {
1✔
64
                        Object newTargetArray = Array.newInstance(type, targetArrayLength + INCREASE_ARRAY_SIZE);
1✔
65
                        System.arraycopy(targetArray, 0, newTargetArray, 0, targetArrayLength);
1✔
66
                        targetArray = newTargetArray;
1✔
67
                    }
68
                    Array.set(targetArray, i, valueAtIndex);
1✔
69
                } catch (ArrayIndexOutOfBoundsException e) {
1✔
70
                    break;
1✔
71
                }
1✔
72
            }
73

74
            if(i < Array.getLength(targetArray)){
1✔
75
                Object newTargetArray = Array.newInstance(type, i);
1✔
76
                System.arraycopy(targetArray, 0, newTargetArray, 0, i);
1✔
77
                targetArray = newTargetArray;
1✔
78
            }
79

80
            return targetArray;
1✔
81
        }
82
    }
83

84
    private static class ArrayIndexedPropertyIterator implements IndexedPropertyIterator {
85

86
        private static final Object[] EMPTY = new Object[0];
1✔
87

88
        private int index = -1;
1✔
89
        private final Object array;
90

91
        public ArrayIndexedPropertyIterator(Object array) {
1✔
92
            this.array = array == null ? EMPTY : array;
1✔
93
        }
1✔
94

95
        @Override
96
        public boolean next() {
97
            int length = Array.getLength(array);
1✔
98
            return ++index < length;
1✔
99
        }
100

101
        @Override
102
        public int getIndex() {
103
            return index;
1✔
104
        }
105

106
        @Override
107
        public Object getValue() {
108
            return Array.get(array, index);
1✔
109
        }
110

111
        @Override
112
        public Object toArray() {
113
            return array == EMPTY ? null : array;
1✔
114
        }
115
    }
116

117
    @Override
118
    public void copy(Property sourceProperty, Property targetProperty) {
119
        boolean indexedSourceProperty = sourceProperty instanceof IndexedProperty;
1✔
120
        boolean indexedTargetProperty = targetProperty instanceof IndexedProperty;
1✔
121

122
        boolean typesDiffer = indexedSourceProperty ^ indexedTargetProperty;
1✔
123
        if (typesDiffer) {
1✔
124
            throwDifferentTypesException(sourceProperty, targetProperty);
×
125
        }
126

127
        if (indexedSourceProperty && indexedTargetProperty) {
1✔
128
            copyIndexedProperty((IndexedProperty) sourceProperty, (IndexedProperty) targetProperty);
1✔
129
        } else {
130
            Object value = sourceProperty.getValue();
1✔
131
            targetProperty.setValue(value);
1✔
132
        }
133
    }
1✔
134

135
    private void copyIndexedProperty(IndexedProperty sourceProperty, IndexedProperty targetProperty) {
136
        IndexedPropertyIterator sourcePropertyValuesIterator = getIndexedPropertyIterator(sourceProperty);
1✔
137

138
        if (targetProperty.getPropertyDesc().isWritable()) {
1✔
139
            Object array = sourcePropertyValuesIterator.toArray();
1✔
140
            targetProperty.setValue(array);
1✔
141
        } else {
1✔
142
            while (sourcePropertyValuesIterator.next()) {
1✔
143
                int index = sourcePropertyValuesIterator.getIndex();
1✔
144
                Object value = sourcePropertyValuesIterator.getValue();
1✔
145
                targetProperty.setValue(index, value);
1✔
146
            }
1✔
147
        }
148
    }
1✔
149

150
    private IndexedPropertyIterator getIndexedPropertyIterator(IndexedProperty property) {
151
        if (property.getPropertyDesc().isReadable()) {
1✔
152
            Object value = property.getValue();
1✔
153
            return new ArrayIndexedPropertyIterator(value);
1✔
154
        } else {
155
            return new OnTheFlyIndexPropertyIterator(property);
1✔
156
        }
157
    }
158

159
    private void throwDifferentTypesException(Property sourceProperty, Property targetProperty) {
160
        StringBuilder sb = new StringBuilder(getClass().getSimpleName());
1✔
161
        sb.append(" can not copy properties of different types:\n");
1✔
162
        sb.append("\t");
1✔
163
        sb.append(sourceProperty);
1✔
164
        sb.append("\n");
1✔
165
        sb.append("\t");
1✔
166
        sb.append(targetProperty);
1✔
167
        throw new IllegalArgumentException(sb.toString());
1✔
168
    }
169
}
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