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-2007 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-release/3.0/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        public RolapMember getLeadMember(RolapMember member, int n) {
064            return substitute(
065                memberReader.getLeadMember(desubstitute(member), n));
066        }
067    
068        public List<RolapMember> getMembersInLevel(
069            RolapLevel level,
070            int startOrdinal,
071            int endOrdinal)
072        {
073            return substitute(
074                memberReader.getMembersInLevel(level, startOrdinal, endOrdinal));
075        }
076    
077        public void getMemberRange(
078            RolapLevel level,
079            RolapMember startMember,
080            RolapMember endMember,
081            List<RolapMember> list)
082        {
083            memberReader.getMemberRange(
084                level,
085                desubstitute(startMember),
086                desubstitute(endMember),
087                new SubstitutingMemberList(list));
088        }
089    
090        public int compare(
091            RolapMember m1,
092            RolapMember m2,
093            boolean siblingsAreEqual)
094        {
095            return memberReader.compare(
096                desubstitute(m1),
097                desubstitute(m2),
098                siblingsAreEqual);
099        }
100    
101        public RolapHierarchy getHierarchy() {
102            return memberReader.getHierarchy();
103        }
104    
105        public boolean setCache(MemberCache cache) {
106            // cache semantics don't make sense if members are not comparable
107            throw new UnsupportedOperationException();
108        }
109    
110        public RolapMember[] getMembers() {
111            // might make sense, but I doubt it
112            throw new UnsupportedOperationException();
113        }
114    
115        public List<RolapMember> getRootMembers() {
116            return substitute(memberReader.getRootMembers());
117        }
118    
119        public void getMemberChildren(
120            RolapMember parentMember,
121            List<RolapMember> children)
122        {
123            memberReader.getMemberChildren(
124                desubstitute(parentMember),
125                new SubstitutingMemberList(children));
126        }
127    
128        public void getMemberChildren(
129            List<RolapMember> parentMembers,
130            List<RolapMember> children)
131        {
132            memberReader.getMemberChildren(
133                desubstitute(parentMembers),
134                new SubstitutingMemberList(children));
135        }
136    
137        public int getMemberCount() {
138            return memberReader.getMemberCount();
139        }
140    
141        public RolapMember lookupMember(
142            List<Id.Segment> uniqueNameParts,
143            boolean failIfNotFound)
144        {
145            return substitute(
146                memberReader.lookupMember(uniqueNameParts, failIfNotFound));
147        }
148    
149        public void getMemberChildren(
150            RolapMember member,
151            List<RolapMember> children,
152            MemberChildrenConstraint constraint)
153        {
154            memberReader.getMemberChildren(
155                desubstitute(member), 
156                new SubstitutingMemberList(children),
157                constraint);
158        }
159    
160        public void getMemberChildren(
161            List<RolapMember> parentMembers,
162            List<RolapMember> children,
163            MemberChildrenConstraint constraint)
164        {
165            memberReader.getMemberChildren(
166                substitute(parentMembers),
167                new SubstitutingMemberList(children),
168                constraint);
169        }
170    
171        public List<RolapMember> getMembersInLevel(
172            RolapLevel level,
173            int startOrdinal,
174            int endOrdinal,
175            TupleConstraint constraint)
176        {
177            return substitute(
178                memberReader.getMembersInLevel(
179                    level, startOrdinal, endOrdinal, constraint));
180        }
181    
182        public RolapMember getDefaultMember() {
183            return substitute(memberReader.getDefaultMember());
184        }
185    
186        public RolapMember getMemberParent(RolapMember member) {
187            return substitute(memberReader.getMemberParent(desubstitute(member)));
188        }
189    
190        public TupleReader.MemberBuilder getMemberBuilder() {
191            return memberBuilder;
192        }
193    
194        /**
195         * List which writes through to an underlying list, substituting members
196         * as they are written and desubstituting as they are read.
197         */
198        private class SubstitutingMemberList extends AbstractList<RolapMember> {
199            private final List<RolapMember> list;
200    
201            SubstitutingMemberList(List<RolapMember> list) {
202                this.list = list;
203            }
204    
205            public RolapMember get(int index) {
206                return desubstitute(list.get(index));
207            }
208    
209            public int size() {
210                return list.size();
211            }
212    
213            public RolapMember set(int index, RolapMember element) {
214                return desubstitute(list.set(index, substitute(element)));
215            }
216    
217            public void add(int index, RolapMember element) {
218                list.add(index, substitute(element));
219            }
220    
221            public RolapMember remove(int index) {
222                return list.remove(index);
223            }
224        }
225    
226        private class SubstitutingMemberBuilder
227            implements TupleReader.MemberBuilder
228        {
229            public MemberCache getMemberCache() {
230                return memberReader.getMemberBuilder().getMemberCache();
231            }
232    
233            public Object getMemberCacheLock() {
234                return memberReader.getMemberBuilder().getMemberCacheLock();
235            }
236    
237            public RolapMember makeMember(
238                RolapMember parentMember,
239                RolapLevel childLevel,
240                Object value,
241                Object captionValue,
242                boolean parentChild,
243                ResultSet resultSet,
244                Object key,
245                int column) throws SQLException
246            {
247                return substitute(
248                    memberReader.getMemberBuilder().makeMember(
249                        desubstitute(parentMember),
250                        childLevel,
251                        value,
252                        captionValue,
253                        parentChild,
254                        resultSet,
255                        key,
256                        column));
257            }
258        }
259    }
260    
261    // End SubstitutingMemberReader.java