001/*
002 * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Stephane Lacoin at Nuxeo (aka matic)
016 */
017package org.nuxeo.connect.tools.report;
018
019import java.util.Iterator;
020import java.util.NoSuchElementException;
021import java.util.Set;
022
023import org.nuxeo.common.xmap.annotation.XNode;
024import org.nuxeo.common.xmap.annotation.XObject;
025import org.nuxeo.connect.tools.report.ReportConfiguration.Contribution;
026import org.nuxeo.runtime.model.SimpleContributionRegistry;
027
028/**
029 * Registry of report contributions, used internally by the component.
030 *
031 * @since 8.3
032 */
033public class ReportConfiguration extends SimpleContributionRegistry<Contribution> implements Iterable<Contribution> {
034
035    interface Filter {
036        boolean accept(Contribution contribution);
037
038        final Filter enabled = new Filter() {
039
040            @Override
041            public boolean accept(Contribution contribution) {
042                return contribution.enabled;
043            }
044
045        };
046
047    }
048
049    class FilteredIterator implements Iterator<Contribution> {
050
051        final Filter filter;
052
053        FilteredIterator(Filter filter) {
054            this.filter = filter;
055        }
056
057        final Iterator<Contribution> iterator = currentContribs.values().iterator();
058
059        Contribution next;
060
061        @Override
062        public boolean hasNext() {
063            return fetch();
064        }
065
066        boolean fetch() {
067            if (next != null) {
068                return true;
069            }
070            while (iterator.hasNext()) {
071                next = iterator.next();
072                if (!filter.accept(next)) {
073                    continue;
074                }
075                return true;
076            }
077            next = null;
078            return false;
079        }
080
081        @Override
082        public Contribution next() {
083            if (!fetch()) {
084                throw new NoSuchElementException("no more reports");
085            }
086            try {
087                return next;
088            } finally {
089                next = null;
090            }
091        }
092    }
093
094    @XObject("report")
095    public static class Contribution {
096
097        @XNode("@name")
098        String name = "noop";
099
100        @XNode("@enabled")
101        boolean enabled = true;
102
103        @XNode("@oftype")
104        public void oftype(Class<? extends ReportWriter> typeof) throws ReflectiveOperationException {
105            writer = typeof.newInstance();
106        }
107
108        ReportWriter writer;
109
110    }
111
112    @Override
113    public String getContributionId(Contribution contrib) {
114        return contrib.name;
115    }
116
117    @Override
118    public boolean isSupportingMerge() {
119        return true;
120    }
121
122    @Override
123    public void merge(Contribution src, Contribution dst) {
124        dst.writer = src.writer;
125        dst.enabled = src.enabled;
126    }
127
128    @Override
129    public Contribution clone(Contribution orig) {
130        Contribution clone = new Contribution();
131        clone.name = orig.name;
132        clone.writer = orig.writer;
133        clone.enabled = orig.enabled;
134        return clone;
135    }
136
137    @Override
138    public java.util.Iterator<Contribution> iterator() {
139        return new FilteredIterator(Filter.enabled);
140    }
141
142    Iterator<Contribution> iterator(Set<String> names) {
143        if (names.isEmpty()) {
144            return iterator();
145        }
146        class OfNames implements Filter {
147            final Set<String> names;
148
149            OfNames(Set<String> names) {
150                this.names = names;
151            }
152
153            @Override
154            public boolean accept(Contribution contribution) {
155                return enabled.accept(contribution) && names.contains(contribution.name);
156            }
157
158        }
159        return new FilteredIterator(new OfNames(names));
160    }
161
162}