/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.esri.gpt.catalog.harvest.repository; import com.esri.gpt.framework.adhoc.AdHocEventFactoryList; import com.esri.gpt.framework.adhoc.AdHocEventList; import com.esri.gpt.catalog.harvest.clients.exceptions.HRConnectionException; import com.esri.gpt.catalog.harvest.clients.exceptions.HRInvalidProtocolException; import com.esri.gpt.catalog.harvest.protocols.HarvestProtocolAgp2Agp; import com.esri.gpt.catalog.harvest.protocols.HarvestProtocolAgs2Agp; import com.esri.gpt.catalog.harvest.protocols.HarvestProtocolNone; import com.esri.gpt.catalog.management.MmdEnums.ApprovalStatus; import com.esri.gpt.control.webharvest.IterationContext; import com.esri.gpt.control.webharvest.protocol.Protocol; import com.esri.gpt.control.webharvest.protocol.ProtocolInvoker; import com.esri.gpt.framework.request.Record; import com.esri.gpt.framework.resource.api.Native; import com.esri.gpt.framework.resource.api.SourceUri; import com.esri.gpt.framework.resource.common.CommonPublishable; import com.esri.gpt.framework.resource.common.UrlUri; import com.esri.gpt.framework.resource.query.QueryBuilder; import com.esri.gpt.framework.util.LogUtil; import com.esri.gpt.framework.util.ResourceXml; import com.esri.gpt.framework.util.UuidUtil; import com.esri.gpt.framework.util.Val; import java.io.IOException; import java.text.ParseException; import java.util.Calendar; import java.util.Date; import java.util.logging.Level; /** * Harvest repository record. * * <p/> * Represents single harvest repository definition. Usually, objects of this * class are stored within <code>HrRecords</code>. Object of the class * <code>HrSelectRequest</code> is being used to read a list of records from the * database. * * @see HrRecords * @see HrSelectRequest */ public class HrRecord extends Record { // class variables ============================================================= // instance variables ========================================================== /** Repository local id. Autogenerated. */ private int _localId = 0; /** Repository unique id. Default: empty string.*/ private String _uuid = ""; /** Owner (user) local id. Default: -1*/ private int _ownerId = -1; /** Date of the first input. Default: current date.*/ private Date _inputDate = new Date(); /** Date of the most recent update. Default: current date. */ private Date _updateDate = new Date(); /** Name of the repository. Default: empty string. */ private String _name = ""; /** Host server url. Default: empty string.*/ private String _hostUrl = ""; /** Theme lookup switch flag. Deafult: <code>false</code>.*/ private boolean _useThemeLookup = false; /** Harvest frequency. Default: <code>Skip</code>.*/ private HarvestFrequency _harvestFrequency = HarvestFrequency.Skip; /** Sending email notificiation switch flag. Default: <code>false</code>.*/ private boolean _sendNotification = false; /** Harvest protocol. Default: <code>HarvestProtocolNone</code>*/ private Protocol _harvestProtocol = new HarvestProtocolNone(); /** Last harvest date. Defaul: <code>null</code> */ private Date _lastHarvestDate; /** Recent job status. Default: {@link RecentJobStatus#Unavailable} */ private RecentJobStatus _recentJobStatus = RecentJobStatus.Unavailable; /** findable */ private boolean findable; /** searchable */ private boolean searchable; /** synchronizable */ private boolean synchronizable; /** approval status */ private ApprovalStatus approvalStatus = ApprovalStatus.defaultValue(); /** last sync date */ private Date lastSyncDate; private boolean searchRequiresLogin; // constructors ================================================================ // properties ================================================================== /** * Gets local id. * Local id is an identity number generated by database. * @return local id */ public int getLocalId() { return _localId; } /** * Sets local id. * Local id is an identity number generated by database. * @param localId local id */ public void setLocalId(int localId) { _localId = localId; } /** * Gets harvest repository UUID. * @return harvest UUID */ public String getUuid() { return _uuid; } /** * Sets harvest repository UUID. * * <p/> * If the <code>uuid</code> argument is invald, UUID becomes an empty * string. * * @param uuid harvest UUID */ public void setUuid(String uuid) { _uuid = UuidUtil.isUuid(uuid) ? uuid : ""; } /** * Gets owner user local id. * @return owner user local id */ public int getOwnerId() { return _ownerId; } /** * Sets owner user local id. * @param ownerId owner user local id */ public void setOwnerId(int ownerId) { _ownerId = ownerId; } /** * Gets the search requires login. * NOTE: custom for NGA * @return the search requires login */ public boolean getSearchRequiresLogin() { return searchRequiresLogin; } /** * Sets the search requires login. * NOTE: custom for NGA * @param searchRequiresLogin the new search requires login */ public void setSearchRequiresLogin(boolean searchRequiresLogin) { this.searchRequiresLogin = searchRequiresLogin; } /** * Gets input date. * @return input date */ public Date getInputDate() { return _inputDate; } /** * Sets input date. * * <p/> * If the <code>inputDate</code> is <code>null</code> than input date is set * to current date. * * @param inputDate input date. */ public void setInputDate(Date inputDate) { _inputDate = inputDate != null ? inputDate : new Date(); } /** * Gets update date. * @return update date */ public Date getUpdateDate() { return _updateDate; } /** * Sets update date. * If the <code>lastHarvestDate</code> is <code>null</code> than update date is * set to current date. * @param updateDate update date */ public void setUpdateDate(Date updateDate) { _updateDate = updateDate != null ? updateDate : new Date(); } /** * Gets name. * @return name */ public String getName() { return _name; } /** * Sets name. * @param name name */ public void setName(String name) { _name = Val.chkStr(name); } /** * Gets host url. * @return host url */ public String getHostUrl() { if (getProtocol() instanceof HarvestProtocolAgp2Agp) { return ((HarvestProtocolAgp2Agp)getProtocol()).getHostUrl(); } else if (getProtocol() instanceof HarvestProtocolAgs2Agp) { return ((HarvestProtocolAgs2Agp)getProtocol()).getHostUrl(); } else { return _hostUrl; } } /** * Sets host url. * @param hostUrl host url */ public void setHostUrl(String hostUrl) { _hostUrl = Val.chkStr(hostUrl); } /** * Gets short version of host url. * @return short version of host url */ public String getHostUrlShort() { String hostUrlShort = getHostUrl(); int slashSearchStart = 0; int protocolEndIndex = hostUrlShort.indexOf("://"); if (protocolEndIndex != -1) { slashSearchStart = protocolEndIndex + "://".length(); } int slashPosition = hostUrlShort.indexOf("/", slashSearchStart); if (slashPosition != -1) { hostUrlShort = hostUrlShort.substring(0, slashPosition); } return hostUrlShort; } /** * Gets harvest protocol. * @return harvest protocol */ public Protocol getProtocol() { return _harvestProtocol; } /** * Sets protocol. * @param protocol protocol */ public void setProtocol(Protocol protocol) { this._harvestProtocol = protocol; } /** * Gets harvest frequency. * @return harvest frequency */ public HarvestFrequency getHarvestFrequency() { return _harvestFrequency; } /** * Sets harvest frequency. * @param harvestFrequency harvest frequency */ public void setHarvestFrequency(HarvestFrequency harvestFrequency) { _harvestFrequency = harvestFrequency; } /** * Gets sending notification switch flag. * @return sending notification switch flag */ public boolean getSendNotification() { return _sendNotification; } /** * Sets sending notification switch flag. * @param sendNotification sending notification switch flag */ public void setSendNotification(boolean sendNotification) { _sendNotification = sendNotification; } /** * Gets last harvest date. * Last harvest date might be <code>null</code> if no harvest performed on * the repository. * @return last harvest date */ public Date getLastHarvestDate() { return _lastHarvestDate; } /** * Sets last harvest date. * @param lastHarvestDate last harvest date */ public void setLastHarvestDate(Date lastHarvestDate) { _lastHarvestDate = lastHarvestDate; } /** * Gets next harvest date. * @return next harvest date or <code>null</code> harvesting not due yet */ public Date getNextHarvestDate() { Date lastHarvestDate = getLastHarvestDate(); HarvestFrequency harvestFrequency = getHarvestFrequency(); switch (harvestFrequency) { case AdHoc: try { AdHocEventList eventList = getAdHocEventList(); if (eventList!=null) { return eventList.getNextHarvestDate(lastHarvestDate); } else { return null; } } catch (ParseException ex) { return null; } default: return harvestFrequency.getDueDate(lastSyncDate); } } /** * Gets ad-hoc event list. * @return ad-hoc event list * @throws ParseException if parsing "ad-hoc" attribute fails */ public AdHocEventList getAdHocEventList() throws ParseException { return AdHocEventFactoryList.getInstance().parse(Val.chkStr(getProtocol().getAdHoc())); } /** * Sets ad-hoc event list. * @param eventList event list */ public void setAdHocEventList(AdHocEventList eventList) { getProtocol().setAdHoc(eventList.getCodes()); } /** * Clears ad-hoc event list. */ public void clearAdHocEventList() { getProtocol().getAttributeMap().remove("ad-hoc"); } /** * Gets recent job status. * @return recent job status */ public RecentJobStatus getRecentJobStatus() { return _recentJobStatus; } /** * Sets recent job status. * @param recentJobStatus recent job status */ /* default */ void setRecentJobStatus(RecentJobStatus recentJobStatus) { _recentJobStatus = recentJobStatus; } /** * Checks if record is findable. * @return <code>true</code> if record is findable */ public boolean getFindable() { return findable; } /** * Sets record is findable. * @param findable <code>true</code> to make record is findable */ public void setFindable(boolean findable) { this.findable = findable; } /** * Checks if records is synchronizable. * @return <code>true</code> if records is synchronizable */ public boolean getSynchronizable() { return synchronizable; } /** * Sets records is synchronizable. * @param synchronizable <code>true</code> to make records is synchronizable */ public void setSynchronizable(boolean synchronizable) { this.synchronizable = synchronizable; } /** * Checks if records is searchable. * @return <code>true</code> if records is searchable */ public boolean getSearchable() { return searchable; } /** * Sets records is searchable. * @param searchable <ocde>true</code> to make records is searchable */ public void setSearchable(boolean searchable) { this.searchable = searchable; } /** * Gets approval status. * @return approval status */ public ApprovalStatus getApprovalStatus() { return approvalStatus; } /** * Sets approval status. * @param approvalStatus approval status */ public void setApprovalStatus(ApprovalStatus approvalStatus) { this.approvalStatus = approvalStatus!=null? approvalStatus: ApprovalStatus.defaultValue(); } /** * Gets last synchronization date. * This is a date when last successful synchronization has been started * @return last synchronization date */ public Date getLastSyncDate() { return lastSyncDate; } /** * Sets last synchronization date. * This is a date when last successful synchronization has been started * @param lastSyncDate last synchronization date */ public void setLastSyncDate(Date lastSyncDate) { this.lastSyncDate = lastSyncDate; } // methods ===================================================================== /** * Creates string representation of the site. * @return string representation of the site */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Uuid:").append(_uuid); sb.append(" protocol:").append(_harvestProtocol.getKind()); sb.append(" name:").append(_name); sb.append(" url:").append(_hostUrl); sb.append(" input date:").append(_inputDate); sb.append(" update date:").append(_updateDate); sb.append(" harvest date:").append(_lastHarvestDate != null ? _lastHarvestDate : "none"); sb.append(" job status:").append(_recentJobStatus.toString()); return sb.toString(); } /** * Checks connection to the remote host. * @throws HRInvalidProtocolException when protocol attributes are invalid * @throws HRConnectionException if connecting remote repository failed * @deprecated replaced with {@link com.esri.gpt.control.webharvest.validator.ValidatorFactory} */ @Deprecated public void checkConnection() throws HRInvalidProtocolException, HRConnectionException { try { Protocol protocol = getProtocol(); String hostUrl = getHostUrl(); ProtocolInvoker.ping(protocol, hostUrl); } catch (Exception ex) { if (ex instanceof HRInvalidProtocolException) { throw (HRInvalidProtocolException) ex; } if (ex instanceof HRConnectionException) { throw (HRConnectionException) ex; } throw new HRConnectionException("Protocol connection exception", ex); } } /** * Checks if is harvest due now. * @return <code>true</code> if harvest is due now */ public boolean getIsHarvestDue() { Date dueDate = getNextHarvestDate(); return dueDate != null ? !(new Date().before(dueDate)) : false; } /** * Creates new query builder. * @param iterationContext iteration context (can be <code>null</code>) * @return query builder or <code>null</code> if no protocol */ public QueryBuilder newQueryBuilder(IterationContext iterationContext) { if (iterationContext==null) { iterationContext = new IterationContext() { @Override public void onIterationException(Exception ex) { } }; } return getProtocol() != null ? getProtocol().newQueryBuilder(iterationContext, getHostUrl()) : null; } // custom types ================================================================ /** * Harvest frequency. */ public enum HarvestFrequency { /** monthly harvest. */ Monthly { @Override public Date getDueDate(Date lastDate) { if (lastDate == null) { return new Date(); } Calendar due = Calendar.getInstance(); due.setTime(lastDate); due.add(Calendar.MONTH, 1); return due.getTime(); } }, /** once every two weeks harvest. */ BiWeekly { @Override public Date getDueDate(Date lastDate) { if (lastDate == null) { return new Date(); } Calendar due = Calendar.getInstance(); due.setTime(lastDate); due.add(Calendar.WEEK_OF_YEAR, 2); return due.getTime(); } }, /** once a week harvest. */ Weekly { @Override public Date getDueDate(Date lastDate) { if (lastDate == null) { return new Date(); } Calendar due = Calendar.getInstance(); due.setTime(lastDate); due.add(Calendar.WEEK_OF_YEAR, 1); return due.getTime(); } }, /** once a day. */ Dayly { @Override public Date getDueDate(Date lastDate) { if (lastDate == null) { return new Date(); } Calendar due = Calendar.getInstance(); due.setTime(lastDate); due.add(Calendar.DAY_OF_YEAR, 1); return due.getTime(); } }, /** once a hour. */ Hourly { @Override public Date getDueDate(Date lastDate) { if (lastDate == null) { return new Date(); } Calendar due = Calendar.getInstance(); due.setTime(lastDate); due.add(Calendar.HOUR_OF_DAY, 1); return due.getTime(); } }, /** one harvest only scheduled. */ Once { @Override public Date getDueDate(Date lastDate) { if (lastDate == null) { return new Date(); } return null; } }, /** do not perform scheduled harvests. */ Skip, /** do ad-hoc scheduled harvest. */ AdHoc; /** * Checks value of the frequency. * @param frequency value of frequency to parseSingle * @return parsed frequency */ public static HarvestFrequency checkValueOf(String frequency) { frequency = Val.chkStr(frequency); for (HarvestFrequency f : values()) { if (f.name().equalsIgnoreCase(frequency)) { return f; } } LogUtil.getLogger().log(Level.SEVERE, "Invalid HarvestFrequency value: {0}", frequency); return HarvestFrequency.Skip; } /** * Gets due date. * @param lastDate date of the last harvest * @return due date of the next harvest or <code>null</code> if no next harvest * required */ public Date getDueDate(Date lastDate) { return null; } } /** * Harvest job status. */ public enum RecentJobStatus { /** Unavailable; no job has been submitted yet. */ Unavailable(-1), /** Job has just been submitted. */ Submited(0), /** Job is running (currently being processed). */ Running(1), /** Job has been completed. */ Completed(2), /** job has been canceled */ Canceled(3); /** Integer id */ private int _intId; /** * Creates instance of the enum * @param intId integer id */ RecentJobStatus(int intId) { _intId = intId; } /** * Gets integer id. * @return integer id */ public int getIntId() { return _intId; } /** * Checks recent job status. * @param name status name. * @return status or <code>Unavailable</code> if unknown status. */ public static RecentJobStatus checkValueOf(String name) { name = Val.chkStr(name); for (RecentJobStatus s : values()) { if (s.name().equalsIgnoreCase(name)) { return s; } } LogUtil.getLogger().log(Level.SEVERE, "Invalid JobStatus value: {0}", name); return RecentJobStatus.Unavailable; } /** * Checks job integer id. * @param intId integer id * @return status or <code>Unavailable</code> if invalid integer id */ public static RecentJobStatus checkValueOf(int intId) { for (RecentJobStatus s : values()) { if (s.getIntId() == intId) { return s; } } LogUtil.getLogger().log(Level.SEVERE, "Invalid JobStatus integer id: {0}", intId); return RecentJobStatus.Unavailable; } } /** * Generates temporary native resource. * @return native resource * @throws IllegalArgumentException if title not provided */ public Native generateNativeResource() throws IllegalArgumentException { return new NativeImpl(new ResourceXml().makeSimpleResourceXml( getName().length()>0? getName(): getHostUrl(), getHostUrl() )); } /** * Native implementation. */ private class NativeImpl extends CommonPublishable implements Native { private String content; public NativeImpl(String content) { this.content = content; } @Override public SourceUri getSourceUri() { return new UrlUri(getHostUrl()); } @Override public String getContent() throws IOException { return content; } } }