001    /*
002    // $Id: //open/mondrian/src/main/mondrian/rolap/NoCacheMemberReader.java#2 $
003    // This software is subject to the terms of the Common Public License
004    // Agreement, available at the following URL:
005    // http://www.opensource.org/licenses/cpl.html.
006    // Copyright (C) 2001-2002 Kana Software, Inc.
007    // Copyright (C) 2004-2005 TONBELLER AG
008    // Copyright (C) 2007-2008 StrateBI
009    // All Rights Reserved.
010    // You must accept the terms of that agreement to use this software.
011    //
012    */
013    
014    package mondrian.rolap;
015    import mondrian.olap.Util;
016    import mondrian.olap.Id;
017    import mondrian.olap.Member;
018    import mondrian.rolap.TupleReader.MemberBuilder;
019    import mondrian.rolap.sql.MemberChildrenConstraint;
020    import mondrian.rolap.sql.TupleConstraint;
021    
022    import java.util.*;
023    import org.apache.log4j.Logger;
024    
025    /**
026     * <code>NoCacheMemberReader</code> implements {@link MemberReader} but
027     * without doing any kind of caching and avoiding to read all members.
028     *
029     * @author jlopez, lcanals
030     * @since 06 October, 2007
031     * @version $Id: //open/mondrian/src/main/mondrian/rolap/NoCacheMemberReader.java#2 $
032     */
033    public class NoCacheMemberReader implements MemberReader, MemberCache {
034        private static final Logger LOGGER =
035                Logger.getLogger(NoCacheMemberReader.class);
036    
037        private final SqlConstraintFactory sqlConstraintFactory =
038                SqlConstraintFactory.instance();
039    
040        private final MemberReader source;
041    
042    
043        NoCacheMemberReader(MemberReader source) {
044            this.source = source;
045            if (!source.setCache(this)) {
046                throw Util.newInternal(
047                        "MemberSource (" + source + ", " + source.getClass() +
048                        ") does not support cache-writeback");
049            }
050        }
051    
052        // implementes MemberCache
053        public boolean isMutable() {
054            return false;
055        }
056    
057        // implementes MemberCache
058        public RolapMember removeMember(Object key) {
059            return null;
060        }
061    
062        // implementes MemberCache
063        public RolapMember removeMemberAndDescendants(Object key) {
064            return null;
065        }
066    
067        // implement MemberReader
068        public RolapHierarchy getHierarchy() {
069            return source.getHierarchy();
070        }
071    
072        // implement MemberCache
073        public boolean setCache(MemberCache cache) {
074            return false;
075        }
076    
077        // implement MemberCache
078        public Object makeKey(final RolapMember parent, final Object key) {
079            LOGGER.debug("Entering makeKey");
080            return new MemberKey(parent, key);
081        }
082    
083        public synchronized RolapMember getMember(final Object key) {
084            return getMember(key, true);
085        }
086    
087        public RolapMember getMember(final Object key,
088                final boolean mustCheckCacheStatus) {
089            LOGGER.debug("Returning null member: no cache");
090            return null;
091        }
092    
093    
094        // implement MemberCache
095        public Object putMember(final Object key, final RolapMember value) {
096            LOGGER.debug("putMember void for no caching");
097            return value;
098        }
099    
100        // implement MemberReader
101        public List<RolapMember> getMembers() {
102            System.out.println("NoCache getMembers");
103            List<RolapMember> v = new ArrayList<RolapMember>();
104            RolapLevel[] levels = (RolapLevel[]) getHierarchy().getLevels();
105            // todo: optimize by walking to children for members we know about
106            for (RolapLevel level : levels) {
107                List<RolapMember> membersInLevel =
108                    getMembersInLevel(level, 0, Integer.MAX_VALUE);
109                v.addAll(membersInLevel);
110            }
111            return v;
112        }
113    
114        public List<RolapMember> getRootMembers() {
115            LOGGER.debug("Getting root members");
116            return source.getRootMembers();
117        }
118    
119    
120        public List<RolapMember> getMembersInLevel(
121                    final RolapLevel level, final int startOrdinal,
122                    final int endOrdinal) {
123            TupleConstraint constraint =
124                    sqlConstraintFactory.getLevelMembersConstraint(null);
125            return getMembersInLevel(level, startOrdinal, endOrdinal, constraint);
126        }
127    
128        public List<RolapMember> getMembersInLevel(
129                final RolapLevel level, final int startOrdinal,
130                final int endOrdinal, final TupleConstraint constraint) {
131            LOGGER.debug("Entering getMembersInLevel");
132            return source.getMembersInLevel(
133                    level, startOrdinal, endOrdinal, constraint);
134        }
135    
136        public void getMemberChildren(
137            final RolapMember parentMember,
138            final List<RolapMember> children)
139        {
140            MemberChildrenConstraint constraint =
141                    sqlConstraintFactory.getMemberChildrenConstraint(null);
142            getMemberChildren(parentMember, children, constraint);
143        }
144    
145        public void getMemberChildren(
146            final RolapMember parentMember,
147            final List<RolapMember> children,
148            final MemberChildrenConstraint constraint)
149        {
150            List<RolapMember> parentMembers = new ArrayList<RolapMember>();
151            parentMembers.add(parentMember);
152            getMemberChildren(parentMembers, children, constraint);
153        }
154    
155        public void getMemberChildren(
156            final List<RolapMember> parentMembers,
157            final List<RolapMember> children)
158        {
159            MemberChildrenConstraint constraint =
160                sqlConstraintFactory.getMemberChildrenConstraint(null);
161            getMemberChildren(parentMembers, children, constraint);
162        }
163    
164        public void getMemberChildren(
165            final List<RolapMember> parentMembers,
166            final List<RolapMember> children,
167            final MemberChildrenConstraint constraint)
168        {
169            assert constraint != null;
170            LOGGER.debug("Entering getMemberChildren");
171            source.getMemberChildren(parentMembers, children, constraint);
172        }
173    
174        public RolapMember lookupMember(
175            final List<Id.Segment> uniqueNameParts,
176            final boolean failIfNotFound)
177        {
178            return RolapUtil.lookupMember(this, uniqueNameParts, failIfNotFound);
179        }
180    
181        public List<RolapMember> getChildrenFromCache(
182            final RolapMember member,
183            final MemberChildrenConstraint constraint)
184        {
185            return null;
186        }
187    
188        public List<RolapMember> getLevelMembersFromCache(
189            final RolapLevel level,
190            final TupleConstraint constraint)
191        {
192            return null;
193        }
194    
195        public void putChildren(
196            final RolapMember member,
197            final MemberChildrenConstraint constraint,
198            final List<RolapMember> children)
199        {
200        }
201    
202        public RolapMember getLeadMember(RolapMember member, int n) {
203            if (n == 0 || member.isNull()) {
204                return member;
205            } else {
206                SiblingIterator iter = new SiblingIterator(this, member);
207                if (n > 0) {
208                    RolapMember sibling = null;
209                    while (n-- > 0) {
210                        if (!iter.hasNext()) {
211                            return (RolapMember) member.getHierarchy()
212                                    .getNullMember();
213                        }
214                        sibling = iter.nextMember();
215                    }
216                    return sibling;
217                } else {
218                    n = -n;
219                    RolapMember sibling = null;
220                    while (n-- > 0) {
221                        if (!iter.hasPrevious()) {
222                            return (RolapMember) member.getHierarchy()
223                                    .getNullMember();
224                        }
225                        sibling = iter.previousMember();
226                    }
227                    return sibling;
228                }
229            }
230        }
231    
232        public void getMemberRange(
233            final RolapLevel level,
234            final RolapMember startMember,
235            final RolapMember endMember,
236            final List<RolapMember> list)
237        {
238            assert startMember != null : "pre";
239            assert endMember != null : "pre";
240            assert startMember.getLevel() == endMember.getLevel()
241                : "pre: startMember.getLevel() == endMember.getLevel()";
242    
243            if (compare(startMember, endMember, false) > 0) {
244                return;
245            }
246            list.add(startMember);
247            if (startMember == endMember) {
248                return;
249            }
250            SiblingIterator siblings = new SiblingIterator(this, startMember);
251            while (siblings.hasNext()) {
252                final RolapMember member = siblings.nextMember();
253                list.add(member);
254                if (member == endMember) {
255                    return;
256                }
257            }
258            throw Util.newInternal("sibling iterator did not hit end point, start="
259                    + startMember
260                    + ", end="
261                    + endMember);
262        }
263    
264        public int getMemberCount() {
265            return source.getMemberCount();
266        }
267    
268        public int compare(final RolapMember m1, final RolapMember m2,
269                           final boolean siblingsAreEqual) {
270            if (m1 == m2) {
271                return 0;
272            }
273            if (m1.getParentMember() == m2.getParentMember()) {
274                // including case where both parents are null
275                if (siblingsAreEqual) {
276                    return 0;
277                } else if (m1.getParentMember() == null) {
278                    // at this point we know that both parent members are null.
279                    int pos1 = -1, pos2 = -1;
280                    List siblingList = getRootMembers();
281                    for (int i = 0, n = siblingList.size(); i < n; i++) {
282                        RolapMember child = (RolapMember) siblingList.get(i);
283                        if (child == m1) {
284                            pos1 = i;
285                        }
286                        if (child == m2) {
287                            pos2 = i;
288                        }
289                    }
290                    if (pos1 == -1) {
291                        throw Util.newInternal(m1 + " not found among siblings");
292                    }
293                    if (pos2 == -1) {
294                        throw Util.newInternal(m2 + " not found among siblings");
295                    }
296                    Util.assertTrue(pos1 != pos2);
297                    return pos1 < pos2 ? -1 : 1;
298                } else {
299                    List<RolapMember> children = new ArrayList<RolapMember>();
300                    getMemberChildren(m1.getParentMember(), children);
301                    int pos1 = -1, pos2 = -1;
302                    for (int i = 0, n = children.size(); i < n; i++) {
303                        RolapMember child = children.get(i);
304                        if (child == m1) {
305                            pos1 = i;
306                        }
307                        if (child == m2) {
308                            pos2 = i;
309                        }
310                    }
311                    if (pos1 == -1) {
312                        throw Util.newInternal(m1 + " not found among siblings");
313                    }
314                    if (pos2 == -1) {
315                        throw Util.newInternal(m2 + " not found among siblings");
316                    }
317                    Util.assertTrue(pos1 != pos2);
318                    return pos1 < pos2 ? -1 : 1;
319                }
320            }
321            int levelDepth1 = m1.getLevel().getDepth();
322            int levelDepth2 = m2.getLevel().getDepth();
323            if (levelDepth1 < levelDepth2) {
324                final int c = compare(m1, m2.getParentMember(), false);
325                return (c == 0) ? -1 : c;
326    
327            } else if (levelDepth1 > levelDepth2) {
328                final int c = compare(m1.getParentMember(), m2, false);
329                return (c == 0) ? 1 : c;
330    
331            } else {
332                return compare(m1.getParentMember(), m2.getParentMember(), false);
333            }
334        }
335    
336        /**
337         * <code>SiblingIterator</code> helps traverse a hierarchy of members, by
338         * remembering the position at each level. Each SiblingIterator has a
339         * parent, to which it defers when the last child of the current member is
340         * reached.
341         */
342        class SiblingIterator {
343            private final MemberReader reader;
344            private final SiblingIterator parentIterator;
345            private List<? extends Member> siblings;
346            private int position;
347    
348            SiblingIterator(MemberReader reader, RolapMember member) {
349                this.reader = reader;
350                RolapMember parent = member.getParentMember();
351                List<RolapMember> siblingList;
352                if (parent == null) {
353                    siblingList = reader.getRootMembers();
354                    this.parentIterator = null;
355                } else {
356                    siblingList = new ArrayList<RolapMember>();
357                    reader.getMemberChildren(parent, siblingList);
358                    this.parentIterator = new SiblingIterator(reader, parent);
359                }
360                this.siblings = siblingList;
361                this.position = -1;
362                for (int i = 0; i < this.siblings.size(); i++) {
363                    if (siblings.get(i) == member) {
364                        this.position = i;
365                        break;
366                    }
367                }
368                if (this.position == -1) {
369                    throw Util.newInternal(
370                        "member " + member + " not found among its siblings");
371                }
372            }
373            boolean hasNext() {
374                return (this.position < this.siblings.size() - 1) ||
375                    (parentIterator != null) &&
376                    parentIterator.hasNext();
377            }
378            Object next() {
379                return nextMember();
380            }
381            RolapMember nextMember() {
382                if (++this.position >= this.siblings.size()) {
383                    if (parentIterator == null) {
384                        throw Util.newInternal("there is no next member");
385                    }
386                    RolapMember parent = parentIterator.nextMember();
387                    List<RolapMember> siblingList = new ArrayList<RolapMember>();
388                    reader.getMemberChildren(parent, siblingList);
389                    this.siblings = siblingList;
390                    this.position = 0;
391                }
392                return (RolapMember) this.siblings.get(this.position);
393            }
394            boolean hasPrevious() {
395                return (this.position > 0) ||
396                    (parentIterator != null) &&
397                    parentIterator.hasPrevious();
398            }
399            Object previous() {
400                return previousMember();
401            }
402            RolapMember previousMember() {
403                if (--this.position < 0) {
404                    if (parentIterator == null) {
405                        throw Util.newInternal("there is no next member");
406                    }
407                    RolapMember parent = parentIterator.previousMember();
408                    List<RolapMember> siblingList = new ArrayList<RolapMember>();
409                    reader.getMemberChildren(parent, siblingList);
410                    this.siblings = siblingList;
411                    this.position = this.siblings.size() - 1;
412                }
413                return (RolapMember) this.siblings.get(this.position);
414            }
415        }
416    
417        public MemberBuilder getMemberBuilder() {
418            return source.getMemberBuilder();
419        }
420    
421        public RolapMember getDefaultMember() {
422            RolapMember defaultMember =
423                (RolapMember) getHierarchy().getDefaultMember();
424            if (defaultMember != null) {
425                return defaultMember;
426            }
427            return (RolapMember) getRootMembers().get(0);
428        }
429    
430        public int getLevelMemberCount(RolapLevel level) {
431            // No need to cache the result: the caller saves the result by calling
432            // RolapLevel.setApproxRowCount
433            return source.getLevelMemberCount(level);
434        }
435    
436        public RolapMember desubstitute(RolapMember member) {
437            return (RolapMember) member;
438        }
439    
440        public RolapMember substitute(RolapMember member) {
441            return (RolapMember) member;
442        }
443    
444        public RolapMember getMemberParent(RolapMember member) {
445            // This method deals with ragged hierarchies but not access-controlled
446            // hierarchies - assume these have RestrictedMemberReader possibly
447            // wrapped in a SubstitutingMemberReader.
448            RolapMember parentMember = (RolapMember) member.getParentMember();
449            // Skip over hidden parents.
450            while (parentMember != null && parentMember.isHidden()) {
451                parentMember = parentMember.getParentMember();
452            }
453            return parentMember;
454        }
455    
456    }
457    
458    // End NoCacheMemberReader.java