001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.relations; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResource; 032import org.opencms.file.CmsResourceFilter; 033import org.opencms.file.CmsVfsResourceNotFoundException; 034import org.opencms.main.CmsException; 035import org.opencms.util.CmsUUID; 036 037import java.util.Comparator; 038 039import com.google.common.base.Objects; 040 041/** 042 * A relation between two opencms resources.<p> 043 * 044 * @since 6.3.0 045 */ 046public class CmsRelation { 047 048 /** 049 * A comparator for the source & target path plus the relation type of 2 relations.<p> 050 */ 051 public static final Comparator<CmsRelation> COMPARATOR = new Comparator<CmsRelation>() { 052 053 /** 054 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) 055 */ 056 public int compare(CmsRelation r1, CmsRelation r2) { 057 058 if (r1 == r2) { 059 return 0; 060 } 061 String p1 = r1.getSourcePath() + r1.getTargetPath() + r1.getType().getId(); 062 String p2 = r2.getSourcePath() + r2.getTargetPath() + r2.getType().getId(); 063 064 return p1.compareTo(p2); 065 } 066 }; 067 068 /** Default value for undefined Strings. */ 069 private static final String UNDEF = ""; 070 071 /** Cached hash code. */ 072 private int m_hashCode; 073 074 /** The structure id of the source resource. */ 075 private final CmsUUID m_sourceId; 076 077 /** The path of the source resource. */ 078 private final String m_sourcePath; 079 080 /** The structure id of the target resource. */ 081 private final CmsUUID m_targetId; 082 083 /** The path of the target resource. */ 084 private final String m_targetPath; 085 086 /** The relation type. */ 087 private final CmsRelationType m_type; 088 089 /** 090 * Creates a new relation object of the given type between the given resources.<p> 091 * 092 * @param source the source resource 093 * @param target the target resource 094 * @param type the relation type 095 */ 096 public CmsRelation(CmsResource source, CmsResource target, CmsRelationType type) { 097 098 this(source.getStructureId(), source.getRootPath(), target.getStructureId(), target.getRootPath(), type); 099 } 100 101 /** 102 * Base constructor.<p> 103 * 104 * @param sourceId the source structure id 105 * @param sourcePath the source path 106 * @param targetId the target structure id 107 * @param targetPath the target path 108 * @param type the relation type 109 */ 110 public CmsRelation(CmsUUID sourceId, String sourcePath, CmsUUID targetId, String targetPath, CmsRelationType type) { 111 112 // make sure no value can ever be null 113 m_sourceId = ((sourceId != null) ? sourceId : CmsUUID.getNullUUID()); 114 m_sourcePath = ((sourcePath != null) ? sourcePath : UNDEF); 115 m_targetId = ((targetId != null) ? targetId : CmsUUID.getNullUUID()); 116 m_targetPath = ((targetPath != null) ? targetPath : UNDEF); 117 m_type = ((type != null) ? type : CmsRelationType.XML_WEAK); 118 } 119 120 /** 121 * @see java.lang.Object#equals(java.lang.Object) 122 */ 123 @Override 124 public boolean equals(Object obj) { 125 126 if (this == obj) { 127 return true; 128 } 129 if (obj instanceof CmsRelation) { 130 CmsRelation other = (CmsRelation)obj; 131 return (m_type == other.m_type) 132 && (Objects.equal(m_sourcePath, other.m_sourcePath) || Objects.equal(m_sourceId, other.m_sourceId)) 133 && (Objects.equal(m_targetPath, other.m_targetPath) || Objects.equal(m_targetId, other.m_targetId)); 134 } 135 return false; 136 } 137 138 /** 139 * Returns the source resource when possible to read with the given filter.<p> 140 * 141 * @param cms the current user context 142 * @param filter the filter to use 143 * 144 * @return the source resource 145 * 146 * @throws CmsException if something goes wrong 147 */ 148 public CmsResource getSource(CmsObject cms, CmsResourceFilter filter) throws CmsException { 149 150 try { 151 // first look up by id 152 return cms.readResource(getSourceId(), filter); 153 } catch (CmsVfsResourceNotFoundException e) { 154 // then look up by name, but from the root site 155 String storedSiteRoot = cms.getRequestContext().getSiteRoot(); 156 try { 157 cms.getRequestContext().setSiteRoot(""); 158 return cms.readResource(getSourcePath(), filter); 159 } finally { 160 cms.getRequestContext().setSiteRoot(storedSiteRoot); 161 } 162 } 163 } 164 165 /** 166 * Returns the structure id of the source resource.<p> 167 * 168 * @return the structure id of the source resource 169 */ 170 public CmsUUID getSourceId() { 171 172 return m_sourceId; 173 } 174 175 /** 176 * Returns the path of the source resource.<p> 177 * 178 * @return the path of the source resource 179 */ 180 public String getSourcePath() { 181 182 return m_sourcePath; 183 } 184 185 /** 186 * Returns the target resource when possible to read with the given filter.<p> 187 * 188 * @param cms the current user context 189 * @param filter the filter to use 190 * 191 * @return the target resource 192 * 193 * @throws CmsException if something goes wrong 194 */ 195 public CmsResource getTarget(CmsObject cms, CmsResourceFilter filter) throws CmsException { 196 197 try { 198 // first look up by id 199 return cms.readResource(getTargetId(), filter); 200 } catch (CmsVfsResourceNotFoundException e) { 201 // then look up by name, but from the root site 202 String storedSiteRoot = cms.getRequestContext().getSiteRoot(); 203 try { 204 cms.getRequestContext().setSiteRoot(""); 205 return cms.readResource(getTargetPath(), filter); 206 } finally { 207 cms.getRequestContext().setSiteRoot(storedSiteRoot); 208 } 209 } 210 } 211 212 /** 213 * Returns the structure id of the target resource.<p> 214 * 215 * @return the structure id of the target resource 216 */ 217 public CmsUUID getTargetId() { 218 219 return m_targetId; 220 } 221 222 /** 223 * Returns the path of the target resource.<p> 224 * 225 * @return the path of the target resource 226 */ 227 public String getTargetPath() { 228 229 return m_targetPath; 230 } 231 232 /** 233 * Returns the relation type.<p> 234 * 235 * @return the relation type 236 */ 237 public CmsRelationType getType() { 238 239 return m_type; 240 } 241 242 /** 243 * @see java.lang.Object#hashCode() 244 */ 245 @Override 246 public int hashCode() { 247 248 if (m_hashCode == 0) { 249 // calculate hash code only once 250 final int PRIME = 31; 251 int result = 1; 252 result = (PRIME * result) + ((m_sourceId == null) ? 0 : m_sourceId.hashCode()); 253 result = (PRIME * result) + ((m_sourcePath == null) ? 0 : m_sourcePath.hashCode()); 254 result = (PRIME * result) + ((m_targetId == null) ? 0 : m_targetId.hashCode()); 255 result = (PRIME * result) + ((m_targetPath == null) ? 0 : m_targetPath.hashCode()); 256 result = (PRIME * result) + ((m_type == null) ? 0 : m_type.hashCode()); 257 m_hashCode = result; 258 } 259 return m_hashCode; 260 } 261 262 /** 263 * @see java.lang.Object#toString() 264 */ 265 @Override 266 public String toString() { 267 268 StringBuffer str = new StringBuffer(); 269 str.append("CmsRelation ["); 270 str.append("source id: ").append(m_sourceId).append(", "); 271 str.append("source path: ").append(m_sourcePath).append(", "); 272 str.append("target id: ").append(m_targetId).append(", "); 273 str.append("target path: ").append(m_targetPath).append(", "); 274 str.append("type: ").append(m_type); 275 str.append("]"); 276 return str.toString(); 277 } 278 279 /** 280 * Copies this relation, but sets the target id in the copy to the given value. 281 * 282 * @param id the new target id for the copy 283 * @return the copy with the target id 284 */ 285 public CmsRelation withTargetId(CmsUUID id) { 286 287 return new CmsRelation(m_sourceId, m_sourcePath, id, m_targetPath, m_type); 288 } 289}