    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      https://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.net.nntp;
    019
    020import java.util.Calendar;
    021import java.util.Objects;
    022
    023/**
    024 * The NewGroupsOrNewsQuery class. This is used to issue NNTP NEWGROUPS and NEWNEWS queries, implemented by
    025 * {@link org.apache.commons.net.nntp.NNTPClient#listNewNewsgroups listNewNewsGroups} and {@link org.apache.commons.net.nntp.NNTPClient#listNewNews listNewNews
    026 * } respectively. It prevents you from having to format date, time, distribution, and newgroup arguments.
    027 * <p>
    028 * You might use the class as follows:
    029 * </p>
    030 *
    031 * <pre>
    032 * query = new NewsGroupsOrNewsQuery(new GregorianCalendar(97, 11, 15), false);
    033 * query.addDistribution("comp");
    034 * NewsgroupInfo[] newsgroups = client.listNewgroups(query);
    035 * </pre>
    036 *
    037 * This will retrieve the list of newsgroups starting with the comp. distribution prefix created since midnight 11/15/97.
    038 *
    039 * @see NNTPClient
    040 */
    041
    042public final class NewGroupsOrNewsQuery {
    043    private final String date;
    044    private final String time;
    045    private StringBuffer distributions;
    046    private StringBuffer newsgroups;
    047    private final boolean isGMT;
    048
    049    /**
    050     * Creates a new query using the given time as a reference point.
    051     *
    052     * @param date The date since which new groups or news have arrived.
    053     * @param gmt  True if the date should be considered as GMT, false if not.
    054     */
    055    public NewGroupsOrNewsQuery(final Calendar date, final boolean gmt) {
    056        int num;
    057        String str;
    058        final StringBuilder buffer;
    059
    060        this.distributions = null;
    061        this.newsgroups = null;
    062        this.isGMT = gmt;
    063
    064        buffer = new StringBuilder();
    065
    066        // Get year
    067        num = date.get(Calendar.YEAR);
    068        str = Integer.toString(num);
    069        num = str.length();
    070
    071        if (num >= 2) {
    072            buffer.append(str.substring(num - 2));
    073        } else {
    074            buffer.append("00");
    075        }
    076
    077        // Get month
    078        num = date.get(Calendar.MONTH) + 1;
    079        str = Integer.toString(num);
    080        num = str.length();
    081
    082        if (num == 1) {
    083            buffer.append('0');
    084            buffer.append(str);
    085        } else if (num == 2) {
    086            buffer.append(str);
    087        } else {
    088            buffer.append("01");
    089        }
    090
    091        // Get day
    092        num = date.get(Calendar.DAY_OF_MONTH);
    093        str = Integer.toString(num);
    094        num = str.length();
    095
    096        if (num == 1) {
    097            buffer.append('0');
    098            buffer.append(str);
    099        } else if (num == 2) {
    100            buffer.append(str);
    101        } else {
    102            buffer.append("01");
    103        }
    104
    105        this.date = buffer.toString();
    106
    107        buffer.setLength(0);
    108
    109        // Get hour
    110        num = date.get(Calendar.HOUR_OF_DAY);
    111        str = Integer.toString(num);
    112        num = str.length();
    113
    114        if (num == 1) {
    115            buffer.append('0');
    116            buffer.append(str);
    117        } else if (num == 2) {
    118            buffer.append(str);
    119        } else {
    120            buffer.append("00");
    121        }
    122
    123        // Get minutes
    124        num = date.get(Calendar.MINUTE);
    125        str = Integer.toString(num);
    126        num = str.length();
    127
    128        if (num == 1) {
    129            buffer.append('0');
    130            buffer.append(str);
    131        } else if (num == 2) {
    132            buffer.append(str);
    133        } else {
    134            buffer.append("00");
    135        }
    136
    137        // Get seconds
    138        num = date.get(Calendar.SECOND);
    139        str = Integer.toString(num);
    140        num = str.length();
    141
    142        if (num == 1) {
    143            buffer.append('0');
    144            buffer.append(str);
    145        } else if (num == 2) {
    146            buffer.append(str);
    147        } else {
    148            buffer.append("00");
    149        }
    150
    151        this.time = buffer.toString();
    152    }
    153
    154    /**
    155     * Add a distribution group to the query. The distribution part of a newsgroup is the segment of the name preceding the first dot (e.g., comp, alt, rec).
    156     * Only those newsgroups matching one of the distributions or, in the case of NEWNEWS, an article in a newsgroup matching one of the distributions, will be
    157     * reported as a query result. Adding distributions is purely optional.
    158     *
    159     * @param distribution A distribution to add to the query.
    160     */
    161    public void addDistribution(final String distribution) {
    162        if (distributions != null) {
    163            distributions.append(',');
    164        } else {
    165            distributions = new StringBuffer();
    166        }
    167        distributions.append(distribution);
    168    }
    169
    170    /**
    171     * Add a newsgroup to the list of newsgroups being queried. Newsgroups added this way are only meaningful to the NEWNEWS command. Newsgroup names may
    172     * include the {@code *} wildcard, as in {@code comp.lang.*} or {@code comp.lang.java.*}. Adding at least one newsgroup is mandatory for
    173     * the NEWNEWS command.
    174     *
    175     * @param newsgroup The newsgroup to add to the list of groups to be checked for new news.
    176     */
    177    public void addNewsgroup(final String newsgroup) {
    178        if (newsgroups != null) {
    179            newsgroups.append(',');
    180        } else {
    181            newsgroups = new StringBuffer();
    182        }
    183        newsgroups.append(newsgroup);
    184    }
    185
    186    /**
    187     * Gets the NNTP query formatted date (year, month, day in the form YYMMDD).
    188     *
    189     * @return The NNTP query formatted date.
    190     */
    191    public String getDate() {
    192        return date;
    193    }
    194
    195    /**
    196     * Gets the comma separated list of distributions. This may be null if there are no distributions.
    197     *
    198     * @return The list of distributions, which may be null if no distributions have been specified.
    199     */
    200    public String getDistributions() {
    201        return Objects.toString(distributions, null);
    202    }
    203
    204    /**
    205     * Gets the comma separated list of newsgroups. This may be null if there are no newsgroups
    206     *
    207     * @return The list of newsgroups, which may be null if no newsgroups have been specified.
    208     */
    209    public String getNewsgroups() {
    210        return Objects.toString(newsgroups, null);
    211    }
    212
    213    /**
    214     * Gets the NNTP query formatted time (hour, minutes, seconds in the form HHMMSS).
    215     *
    216     * @return The NNTP query formatted time.
    217     */
    218    public String getTime() {
    219        return time;
    220    }
    221
    222    /**
    223     * Tests whether or not the query date should be treated as GMT.
    224     *
    225     * @return True if the query date is to be treated as GMT, false if not.
    226     */
    227    public boolean isGMT() {
    228        return isGMT;
    229    }
    230
    231    /**
    232     * Add a newsgroup to the list of newsgroups being queried, but indicate that group should not be checked for new news. Newsgroups added this way are only
    233     * meaningful to the NEWNEWS command. Newsgroup names may include the {@code *} wildcard, as in {@code comp.lang.*} or
    234     * {@code comp.lang.java.*}.
    235     * <p>
    236     * The following would create a query that searched for new news in all comp.lang.java newsgroups except for comp.lang.java.advocacy.
    237     * </p>
    238     *
    239     * <pre>
    240     * query.addNewsgroup("comp.lang.java.*");
    241     * query.omitNewsgroup("comp.lang.java.advocacy");
    242     * </pre>
    243     *
    244     * @param newsgroup The newsgroup to add to the list of groups to be checked for new news, but which should be omitted from the search for new news.
    245     */
    246    public void omitNewsgroup(final String newsgroup) {
    247        addNewsgroup("!" + newsgroup);
    248    }
    249}