001    /*
002    // This software is subject to the terms of the Common Public License
003    // Agreement, available at the following URL:
004    // http://www.opensource.org/licenses/cpl.html.
005    // Copyright (C) 2007-2008 Julian Hyde
006    // All Rights Reserved.
007    // You must accept the terms of that agreement to use this software.
008    */
009    package mondrian.rolap;
010    
011    import mondrian.olap.Id;
012    import mondrian.rolap.sql.MemberChildrenConstraint;
013    import mondrian.rolap.sql.TupleConstraint;
014    
015    import java.util.*;
016    import java.sql.ResultSet;
017    import java.sql.SQLException;
018    
019    /**
020     * Implementation of {@link MemberReader} which replaces given members
021     * with a substitute.
022     *
023     * <p>Derived classes must implement the {@link #substitute(RolapMember)} and
024     * {@link #desubstitute(RolapMember)} methods.
025     *
026     * @author jhyde
027     * @version $Id: //open/mondrian/src/main/mondrian/rolap/SubstitutingMemberReader.java#4 $
028     * @since Oct 5, 2007
029     */
030    public abstract class SubstitutingMemberReader extends DelegatingMemberReader {
031        private final TupleReader.MemberBuilder memberBuilder =
032            new SubstitutingMemberBuilder();
033    
034        /**
035         * Creates a SubstitutingMemberReader.
036         *
037         * @param memberReader Parent member reader
038         */
039        SubstitutingMemberReader(MemberReader memberReader) {
040            super(memberReader);
041        }
042    
043        // Helper methods
044    
045        private List<RolapMember> desubstitute(List<RolapMember> members) {
046            List<RolapMember> list = new ArrayList<RolapMember>(members.size());
047            for (RolapMember member : members) {
048                list.add(desubstitute(member));
049            }
050            return list;
051        }
052    
053        private List<RolapMember> substitute(List<RolapMember> members) {
054            List<RolapMember> list = new ArrayList<RolapMember>(members.size());
055            for (RolapMember member : members) {
056                list.add(substitute(member));
057            }
058            return list;
059        }
060    
061        // ~ -- Implementations of MemberReader methods ---------------------------
062    
063        @Override
064        public RolapMember getLeadMember(RolapMember member, int n) {
065            return substitute(
066                memberReader.getLeadMember(desubstitute(member), n));
067        }
068    
069        @Override
070        public List<RolapMember> getMembersInLevel(
071            RolapLevel level,
072            int startOrdinal,
073            int endOrdinal)
074        {
075            return substitute(
076                memberReader.getMembersInLevel(level, startOrdinal, endOrdinal));
077        }
078    
079        @Override
080        public void getMemberRange(
081            RolapLevel level,
082            RolapMember startMember,
083            RolapMember endMember,
084            List<RolapMember> list)
085        {
086            memberReader.getMemberRange(
087                level,
088                desubstitute(startMember),
089                desubstitute(endMember),
090                new SubstitutingMemberList(list));
091        }
092    
093        @Override
094        public int compare(
095            RolapMember m1,
096            RolapMember m2,
097            boolean siblingsAreEqual)
098        {
099            return memberReader.compare(
100                desubstitute(m1),
101                desubstitute(m2),
102                siblingsAreEqual);
103        }
104    
105        @Override
106        public RolapHierarchy getHierarchy() {
107            return memberReader.getHierarchy();
108        }
109    
110        @Override
111        public boolean setCache(MemberCache cache) {
112            // cache semantics don't make sense if members are not comparable
113            throw new UnsupportedOperationException();
114        }
115    
116        @Override
117        public List<RolapMember> getMembers() {
118            // might make sense, but I doubt it
119            throw new UnsupportedOperationException();
120        }
121    
122        @Override
123        public List<RolapMember> getRootMembers() {
124            return substitute(memberReader.getRootMembers());
125        }
126    
127        @Override
128        public void getMemberChildren(
129            RolapMember parentMember,
130            List<RolapMember> children)
131        {
132            memberReader.getMemberChildren(
133                desubstitute(parentMember),
134                new SubstitutingMemberList(children));
135        }
136    
137        @Override
138        public void getMemberChildren(
139            List<RolapMember> parentMembers,
140            List<RolapMember> children)
141        {
142            memberReader.getMemberChildren(
143                desubstitute(parentMembers),
144                new SubstitutingMemberList(children));
145        }
146    
147        @Override
148        public int getMemberCount() {
149            return memberReader.getMemberCount();
150        }
151    
152        @Override
153        public RolapMember lookupMember(
154            List<Id.Segment> uniqueNameParts,
155            boolean failIfNotFound)
156        {
157            return substitute(
158                memberReader.lookupMember(uniqueNameParts, failIfNotFound));
159        }
160    
161        @Override
162        public void getMemberChildren(
163            RolapMember member,
164            List<RolapMember> children,
165            MemberChildrenConstraint constraint)
166        {
167            memberReader.getMemberChildren(
168                desubstitute(member),
169                new SubstitutingMemberList(children),
170                constraint);
171        }
172    
173        @Override
174        public void getMemberChildren(
175            List<RolapMember> parentMembers,
176            List<RolapMember> children,
177            MemberChildrenConstraint constraint)
178        {
179            memberReader.getMemberChildren(
180                substitute(parentMembers),
181                new SubstitutingMemberList(children),
182                constraint);
183        }
184    
185        @Override
186        public List<RolapMember> getMembersInLevel(
187            RolapLevel level,
188            int startOrdinal,
189            int endOrdinal,
190            TupleConstraint constraint)
191        {
192            return substitute(
193                memberReader.getMembersInLevel(
194                    level, startOrdinal, endOrdinal, constraint));
195        }
196    
197        @Override
198        public RolapMember getDefaultMember() {
199            return substitute(memberReader.getDefaultMember());
200        }
201    
202        @Override
203        public RolapMember getMemberParent(RolapMember member) {
204            return substitute(memberReader.getMemberParent(desubstitute(member)));
205        }
206    
207        @Override
208        public TupleReader.MemberBuilder getMemberBuilder() {
209            return memberBuilder;
210        }
211    
212        /**
213         * List which writes through to an underlying list, substituting members
214         * as they are written and desubstituting as they are read.
215         */
216        private class SubstitutingMemberList extends AbstractList<RolapMember> {
217            private final List<RolapMember> list;
218    
219            SubstitutingMemberList(List<RolapMember> list) {
220                this.list = list;
221            }
222    
223            @Override
224            public RolapMember get(int index) {
225                return desubstitute(list.get(index));
226            }
227    
228            @Override
229            public int size() {
230                return list.size();
231            }
232    
233            @Override
234            public RolapMember set(int index, RolapMember element) {
235                return desubstitute(list.set(index, substitute(element)));
236            }
237    
238            @Override
239            public void add(int index, RolapMember element) {
240                list.add(index, substitute(element));
241            }
242    
243            @Override
244            public RolapMember remove(int index) {
245                return list.remove(index);
246            }
247        }
248    
249        private class SubstitutingMemberBuilder
250            implements TupleReader.MemberBuilder
251        {
252            public MemberCache getMemberCache() {
253                return memberReader.getMemberBuilder().getMemberCache();
254            }
255    
256            public Object getMemberCacheLock() {
257                return memberReader.getMemberBuilder().getMemberCacheLock();
258            }
259    
260            public RolapMember makeMember(
261                RolapMember parentMember,
262                RolapLevel childLevel,
263                Object value,
264                Object captionValue,
265                boolean parentChild,
266                ResultSet resultSet,
267                Object key,
268                int column) throws SQLException
269            {
270                return substitute(
271                    memberReader.getMemberBuilder().makeMember(
272                        desubstitute(parentMember),
273                        childLevel,
274                        value,
275                        captionValue,
276                        parentChild,
277                        resultSet,
278                        key,
279                        column));
280            }
281        }
282    }
283    
284    // End SubstitutingMemberReader.java