001/* 002 * #%L 003 * Netarchivesuite - harvester 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023package dk.netarkivet.harvester.datamodel; 024 025import java.io.Serializable; 026 027import javax.servlet.jsp.PageContext; 028 029import dk.netarkivet.common.exceptions.ArgumentNotValid; 030import dk.netarkivet.common.utils.I18n; 031 032/** 033 * Harvest channels are used to dispatch harvest jobs to specific pools of crawlers. Channels can accept either only 034 * snapshot jobs or only focused jobs. Snapshot crawls all use a single hard-coded channel. 035 * <p> 036 * Harvest channels names must only contain alphanumeric characters, the constraint is enforced at creation time. 037 * <p> 038 * {@link HarvestDefinition}s are mapped to a {@link HarvestChannel}, and HarvestControllers listen to jobs sent 039 * on a specific channel. 040 * <p> 041 * Harvest channels are stored in the harvest database, as well as mappings to {@link HarvestDefinition}s and 042 * HarvestControllers through two association tables. 043 * <p> 044 * There must be exactly one channel defined as default for every type of job (snapshot and focused). This constraint 045 * will be enforced by the DAO. 046 * 047 * @author ngiraud 048 */ 049@SuppressWarnings("serial") 050public class HarvestChannel implements Serializable { 051 052 /** The unique {@link dk.netarkivet.harvester.datamodel.HarvestChannel} for snapshot harvests. */ 053 // public static final HarvestChannel SNAPSHOT = new HarvestChannel(); 054 055 /** Defines acceptable channel names: at least one word character. */ 056 public static final String ACCEPTABLE_NAME_PATTERN = "^\\w+$"; 057 058 /** The unique numeric id. */ 059 private long id; 060 061 /** 062 * The unique name of the channel. Accepts only alpha numeric characters. 063 * 064 * @see #ACCEPTABLE_NAME_PATTERN 065 * @see #isAcceptableName(String) 066 */ 067 private String name; 068 069 /* Whether this channels type is snapshot or focused. */ 070 private boolean isSnapshot; 071 072 /** Whether this channel is the default one for the given type (snapshot or focused). */ 073 private boolean isDefault; 074 075 /** Comments. */ 076 private String comments; 077 078 /** 079 * Used to build the {@link #SNAPSHOT} singleton only. 080 */ 081 /* 082 * private HarvestChannel() { this.name = Settings.get(HarvesterSettings.SNAPSHOT_HARVEST_CHANNEL_ID); 083 * this.isSnapshot = true; this.isDefault = true; this.comments = ""; } 084 */ 085 086 /** 087 * Constructor from name and comments 088 * 089 * @param name channel name 090 * @param isSnapshot whether this channels type is snapshot or focused 091 * @param isDefault whether this channel is the default one 092 * @param comments user comments (snapshot or focused) 093 * @throws ArgumentNotValid if the name is incorrect. 094 */ 095 public HarvestChannel(String name, boolean isSnapshot, boolean isDefault, String comments) { 096 if (!isAcceptableName(name)) { 097 throw new ArgumentNotValid("'" + name + "' does not match pattern '" + ACCEPTABLE_NAME_PATTERN + "'"); 098 } 099 this.name = name; 100 this.isSnapshot = isSnapshot; 101 this.isDefault = isDefault; 102 this.comments = comments; 103 } 104 105 /** 106 * Constructor from persistent storage 107 * 108 * @param id the channel id 109 * @param name channel name 110 * @param isSnapshot whether this channels type is snapshot or focused 111 * @param isDefault whether this channel is the default one for the given type 112 * @param comments user comments 113 * @throws ArgumentNotValid if the name is incorrect. 114 */ 115 public HarvestChannel(long id, String name, boolean isSnapshot, boolean isDefault, String comments) { 116 ArgumentNotValid.checkNotNullOrEmpty(name, "name"); 117 if (!isAcceptableName(name)) { 118 throw new ArgumentNotValid("'" + name + "' does not match pattern '" + ACCEPTABLE_NAME_PATTERN + "'"); 119 } 120 this.id = id; 121 this.name = name; 122 this.isSnapshot = isSnapshot; 123 this.isDefault = isDefault; 124 this.comments = comments; 125 } 126 127 /** 128 * @return the unique identifier in the persistent storage 129 */ 130 public long getId() { 131 return id; 132 } 133 134 /** 135 * @return the harvest channel name. 136 */ 137 public String getName() { 138 return name; 139 } 140 141 /** 142 * Sets the harvest channel name 143 * 144 * @param name the name to set 145 */ 146 public void setName(String name) { 147 this.name = name; 148 } 149 150 /** 151 * @return true if this channel is intended for snaphsot harvests, false if it is intended for focused ones. 152 */ 153 public boolean isSnapshot() { 154 return isSnapshot; 155 } 156 157 /** 158 * Set the harvest type to snapshot or focused. 159 * 160 * @param isSnapshot true if snapshot, false if focused 161 */ 162 public void setSnapshot(boolean isSnapshot) { 163 this.isSnapshot = isSnapshot; 164 } 165 166 /** 167 * @return true if the channel is the default one for the harvest type (snapshot or focused), false otherwise. 168 */ 169 public boolean isDefault() { 170 return isDefault; 171 } 172 173 /** 174 * Set whether if the channel is the default one for the harvest type (snapshot or focused). 175 * 176 * @param isDefault true if default, false otherwise 177 */ 178 public void setDefault(boolean isDefault) { 179 this.isDefault = isDefault; 180 } 181 182 /** 183 * @return the associated comments. 184 */ 185 public String getComments() { 186 return comments; 187 } 188 189 /** 190 * Sets the associated comments 191 * 192 * @param comments the comments to set 193 */ 194 public void setComments(String comments) { 195 this.comments = comments; 196 } 197 198 /** 199 * Renders a localized description for the singleton. 200 * 201 * @param context 202 * @return a localized description. 203 */ 204 public static String getSnapshotDescription(PageContext context) { 205 return I18n.getString(dk.netarkivet.harvester.Constants.TRANSLATIONS_BUNDLE, context.getResponse().getLocale(), 206 "harvest.channel.snapshot.desc"); 207 } 208 209 /** 210 * Returns true if the given input is an acceptable channel name. 211 * 212 * @param input the candidate name. 213 * @return true if the name complies to the defined {@link #ACCEPTABLE_NAME_PATTERN}, false otherwise 214 */ 215 public static boolean isAcceptableName(String input) { 216 return input.matches(ACCEPTABLE_NAME_PATTERN); 217 } 218 219 @Override 220 public String toString() { 221 return "HarvestChannel [id=" + id + ", name=" + name + ", comments=" + comments + ", isSnapShot=" + isSnapshot 222 + ", isDefault=" + isDefault + "]"; 223 } 224 225}