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.i18n.CmsMessages; 031import org.opencms.main.CmsIllegalArgumentException; 032import org.opencms.main.CmsInitException; 033import org.opencms.main.OpenCms; 034 035import java.io.Serializable; 036import java.util.ArrayList; 037import java.util.Arrays; 038import java.util.Collection; 039import java.util.Collections; 040import java.util.Iterator; 041import java.util.List; 042import java.util.Locale; 043 044/** 045 * Wrapper class for 046 * the different types of relations.<p> 047 * 048 * The possibles values are:<br> 049 * <ul> 050 * <li>{@link #HYPERLINK}</li> 051 * <li>{@link #EMBEDDED_IMAGE}</li> 052 * <li>{@link #EMBEDDED_OBJECT}</li> 053 * <li>{@link #XML_STRONG}</li> 054 * <li>{@link #XML_WEAK}</li> 055 * <li>{@link #JSP_STRONG}</li> 056 * <li>{@link #JSP_WEAK}</li> 057 * <li>{@link #OU_RESOURCE}</li> 058 * <li>{@link #CATEGORY}</li> 059 * <li>{@link #XSD}</li> 060 * </ul> 061 * <p> 062 * 063 * User defined relation types are also available.<p> 064 * 065 * @since 6.3.0 066 */ 067public final class CmsRelationType implements Serializable { 068 069 /** 070 * Enum representing how relations should be handled while copying resources.<p> 071 */ 072 public enum CopyBehavior { 073 /** Copy the relation when copying a resource. */ 074 copy, 075 076 /** Ignore the relation when copying a resource. */ 077 ignore; 078 } 079 080 // the following strings must not be public because they confuse the interface 081 // this means we can't sort this class members according to standard 082 /** String prefix for 'JSP relations. */ 083 private static final String PREFIX_JSP = "JSP_"; 084 085 /** String prefix for XML relations. */ 086 private static final String PREFIX_XML = "XML_"; 087 088 /** String constant for "STRONG" relations. */ 089 private static final String VALUE_STRONG = "STRONG"; 090 091 /** String constant for "WEAK" relations. */ 092 private static final String VALUE_WEAK = "WEAK"; 093 094 /** Constant for the category of an <code>OpenCmsVfsFile</code>. */ 095 public static final CmsRelationType CATEGORY = new CmsRelationType(9, "CATEGORY", false, false, CopyBehavior.copy); 096 097 /** Constant for the <code><img src=''></code> tag in a html page/element. */ 098 public static final CmsRelationType EMBEDDED_IMAGE = new CmsRelationType(2, "IMG", true, true, CopyBehavior.copy); 099 100 /** Constant for the <code><embed src=''></code> tag in a html page/element. */ 101 public static final CmsRelationType EMBEDDED_OBJECT = new CmsRelationType( 102 7, 103 "OBJECT", 104 true, 105 true, 106 CopyBehavior.copy); 107 108 /** Constant for the <code><a href=''></code> tag in a html page/element. */ 109 public static final CmsRelationType HYPERLINK = new CmsRelationType(1, "A", false, true, CopyBehavior.copy); 110 111 /** Constant for the all types of links in a jsp file using the <code>link.strong</code> macro. */ 112 public static final CmsRelationType JSP_STRONG = new CmsRelationType( 113 5, 114 PREFIX_JSP + VALUE_STRONG, 115 true, 116 true, 117 CopyBehavior.copy); 118 119 /** Constant for the all types of links in a jsp file using the <code>link.weak</code> macro. */ 120 public static final CmsRelationType JSP_WEAK = new CmsRelationType( 121 6, 122 PREFIX_JSP + VALUE_WEAK, 123 false, 124 true, 125 CopyBehavior.copy); 126 127 /** Constant for the organizational units resource associations. */ 128 public static final CmsRelationType OU_RESOURCE = new CmsRelationType(8, "OU", false, false, CopyBehavior.copy); 129 130 /** Constant for the <code>OpenCmsVfsFile</code> values in xml content that were defined as 'strong' links. */ 131 public static final CmsRelationType XML_STRONG = new CmsRelationType( 132 3, 133 PREFIX_XML + VALUE_STRONG, 134 true, 135 true, 136 CopyBehavior.copy); 137 138 /** Constant for the <code>OpenCmsVfsFile</code> values in xml content that were defined as 'weak' links. */ 139 public static final CmsRelationType XML_WEAK = new CmsRelationType( 140 4, 141 PREFIX_XML + VALUE_WEAK, 142 false, 143 true, 144 CopyBehavior.copy); 145 146 /** Constant for the type of relations between resources which are locale variants. */ 147 public static final CmsRelationType LOCALE_VARIANT = new CmsRelationType( 148 11, 149 "LOCALE_VARIANT", 150 true, 151 false, 152 CopyBehavior.ignore); 153 154 /** Constant for the type of relations between a detail content and its detail-only container pages. */ 155 public static final CmsRelationType DETAIL_ONLY = new CmsRelationType( 156 12, 157 "DETAIL_ONLY", 158 true, 159 false, 160 CopyBehavior.ignore); 161 162 /** Constant for the weak links from xmlcontent to the used xsd. */ 163 public static final CmsRelationType XSD = new CmsRelationType(10, "XSD", true, true, CopyBehavior.copy); 164 165 /** Serial version UID required for safe serialization. */ 166 private static final long serialVersionUID = -4060567973007877250L; 167 168 /** Constant indicating the starting mode for user defined relation types. */ 169 private static final int USER_DEFINED_MODE_LIMIT = 100; 170 171 /** Array constant for all available system relation types. */ 172 private static final CmsRelationType[] VALUE_ARRAY = { 173 HYPERLINK, 174 EMBEDDED_IMAGE, 175 XML_STRONG, 176 XML_WEAK, 177 JSP_STRONG, 178 JSP_WEAK, 179 EMBEDDED_OBJECT, 180 OU_RESOURCE, 181 CATEGORY, 182 XSD, 183 LOCALE_VARIANT, 184 DETAIL_ONLY}; 185 186 /** The copy behavior. */ 187 private CopyBehavior m_copyBehavior = CopyBehavior.copy; 188 189 /** Flag to indicate if the relations of this type are parsed from the content or not. */ 190 private final boolean m_defInContent; 191 192 /** Internal representation. */ 193 private final int m_id; 194 195 /** Some name for this relation type, ie. for <link> tag representation. */ 196 private final String m_name; 197 198 /** Flag to indicate if the relations of this type are strong or weak. */ 199 private final boolean m_strong; 200 201 /** 202 * Public constructor for user defined relation types.<p> 203 * 204 * @param id the id of the relation type 205 * @param name the name of the relation 206 * @param type the type of relation type, strong or weak 207 */ 208 public CmsRelationType(int id, String name, String type) { 209 210 m_name = name.toUpperCase(); 211 if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_2_INITIALIZING) { 212 // allow relation type definitions only during startup 213 throw new CmsInitException(Messages.get().container(Messages.ERR_RELATION_TYPE_INIT_1, m_name)); 214 } 215 m_strong = type.toUpperCase().equals(VALUE_STRONG); 216 m_defInContent = false; 217 m_id = USER_DEFINED_MODE_LIMIT + id; 218 } 219 220 /** 221 * Private constructor for system relation types.<p> 222 * 223 * @param id the internal representation 224 * @param name the name of the relation 225 * @param strong if the relation is strong or weak 226 * @param defInContent <code>true</code> if the link is defined in the content 227 * @param copyBehavior the copy behavior of the content 228 */ 229 private CmsRelationType(int id, String name, boolean strong, boolean defInContent, CopyBehavior copyBehavior) { 230 231 m_id = id; 232 m_name = name; 233 m_strong = strong; 234 m_defInContent = defInContent; 235 m_copyBehavior = copyBehavior; 236 } 237 238 /** 239 * Returns all relation types in the given list that define relations in the content.<p> 240 * 241 * @param relationTypes the collection of relation types to filter 242 * 243 * @return a list of {@link CmsRelationType} objects 244 */ 245 public static List<CmsRelationType> filterDefinedInContent(Collection<CmsRelationType> relationTypes) { 246 247 List<CmsRelationType> result = new ArrayList<CmsRelationType>(relationTypes); 248 Iterator<CmsRelationType> it = result.iterator(); 249 while (it.hasNext()) { 250 CmsRelationType type = it.next(); 251 if (!type.isDefinedInContent()) { 252 it.remove(); 253 } 254 } 255 return result; 256 } 257 258 /** 259 * Returns all internal defined relation types in the given list.<p> 260 * 261 * @param relationTypes the collection of relation types to filter 262 * 263 * @return a list of {@link CmsRelationType} objects 264 */ 265 public static List<CmsRelationType> filterInternal(Collection<CmsRelationType> relationTypes) { 266 267 List<CmsRelationType> result = new ArrayList<CmsRelationType>(relationTypes); 268 Iterator<CmsRelationType> it = result.iterator(); 269 while (it.hasNext()) { 270 CmsRelationType type = it.next(); 271 if (!type.isInternal()) { 272 it.remove(); 273 } 274 } 275 return result; 276 } 277 278 /** 279 * Returns all relation types in the given list that are not defined in the content.<p> 280 * 281 * @param relationTypes the collection of relation types to filter 282 * 283 * @return a list of {@link CmsRelationType} objects 284 */ 285 public static List<CmsRelationType> filterNotDefinedInContent(Collection<CmsRelationType> relationTypes) { 286 287 List<CmsRelationType> result = new ArrayList<CmsRelationType>(relationTypes); 288 Iterator<CmsRelationType> it = result.iterator(); 289 while (it.hasNext()) { 290 CmsRelationType type = it.next(); 291 if (type.isDefinedInContent()) { 292 it.remove(); 293 } 294 } 295 return result; 296 } 297 298 /** 299 * Returns all strong relation types in the given list.<p> 300 * 301 * @param relationTypes the collection of relation types to filter 302 * 303 * @return a list of {@link CmsRelationType} objects 304 */ 305 public static List<CmsRelationType> filterStrong(Collection<CmsRelationType> relationTypes) { 306 307 List<CmsRelationType> result = new ArrayList<CmsRelationType>(relationTypes); 308 Iterator<CmsRelationType> it = result.iterator(); 309 while (it.hasNext()) { 310 CmsRelationType type = it.next(); 311 if (!type.isStrong()) { 312 it.remove(); 313 } 314 } 315 return result; 316 } 317 318 /** 319 * Returns all user defined relation types in the given list.<p> 320 * 321 * @param relationTypes the collection of relation types to filter 322 * 323 * @return a list of {@link CmsRelationType} objects 324 */ 325 public static List<CmsRelationType> filterUserDefined(Collection<CmsRelationType> relationTypes) { 326 327 List<CmsRelationType> result = new ArrayList<CmsRelationType>(relationTypes); 328 Iterator<CmsRelationType> it = result.iterator(); 329 while (it.hasNext()) { 330 CmsRelationType type = it.next(); 331 if (type.isInternal()) { 332 it.remove(); 333 } 334 } 335 return result; 336 } 337 338 /** 339 * Returns all weak relation types in the given list.<p> 340 * 341 * @param relationTypes the collection of relation types to filter 342 * 343 * @return a list of {@link CmsRelationType} objects 344 */ 345 public static List<CmsRelationType> filterWeak(Collection<CmsRelationType> relationTypes) { 346 347 List<CmsRelationType> result = new ArrayList<CmsRelationType>(relationTypes); 348 Iterator<CmsRelationType> it = result.iterator(); 349 while (it.hasNext()) { 350 CmsRelationType type = it.next(); 351 if (type.isStrong()) { 352 it.remove(); 353 } 354 } 355 return result; 356 } 357 358 /** 359 * Returns all relation types.<p> 360 * 361 * @return a list of {@link CmsRelationType} objects 362 */ 363 public static List<CmsRelationType> getAll() { 364 365 List<CmsRelationType> all = new ArrayList<CmsRelationType>(Arrays.asList(VALUE_ARRAY)); 366 all.addAll(OpenCms.getResourceManager().getRelationTypes()); 367 return Collections.unmodifiableList(all); 368 } 369 370 /** 371 * Returns all relation types for relations defined in the content.<p> 372 * 373 * @return a list of {@link CmsRelationType} objects 374 */ 375 public static List<CmsRelationType> getAllDefinedInContent() { 376 377 return filterDefinedInContent(getAll()); 378 } 379 380 /** 381 * Returns all internally defined relation types.<p> 382 * 383 * @return a list of {@link CmsRelationType} objects 384 */ 385 public static List<CmsRelationType> getAllInternal() { 386 387 return Collections.unmodifiableList(Arrays.asList(VALUE_ARRAY)); 388 } 389 390 /** 391 * Returns all relation types for relations that are not defined in the content.<p> 392 * 393 * @return a list of {@link CmsRelationType} objects 394 */ 395 public static List<CmsRelationType> getAllNotDefinedInContent() { 396 397 return filterNotDefinedInContent(getAll()); 398 } 399 400 /** 401 * Returns all strong relation types.<p> 402 * 403 * @return a list of {@link CmsRelationType} objects 404 */ 405 public static List<CmsRelationType> getAllStrong() { 406 407 return filterStrong(getAll()); 408 } 409 410 /** 411 * Returns all user defined relation types.<p> 412 * 413 * @return a list of {@link CmsRelationType} objects 414 */ 415 public static List<CmsRelationType> getAllUserDefined() { 416 417 return OpenCms.getResourceManager().getRelationTypes(); 418 } 419 420 /** 421 * Returns all weak relation types.<p> 422 * 423 * @return a list of {@link CmsRelationType} objects 424 */ 425 public static List<CmsRelationType> getAllWeak() { 426 427 return filterWeak(getAll()); 428 } 429 430 /** 431 * Parses an <code>int</code> into a relation type.<p> 432 * 433 * @param id the internal representation number to parse 434 * 435 * @return the enumeration element 436 * 437 * @throws CmsIllegalArgumentException if the given value could not be matched against a 438 * <code>{@link CmsRelationType}</code> object. 439 */ 440 public static CmsRelationType valueOf(int id) throws CmsIllegalArgumentException { 441 442 if ((id > 0) && (id <= VALUE_ARRAY.length)) { 443 return VALUE_ARRAY[id - 1]; 444 } 445 id -= USER_DEFINED_MODE_LIMIT; 446 if ((id >= 0) && (id < getAllUserDefined().size())) { 447 return getAllUserDefined().get(id); 448 } 449 throw new CmsIllegalArgumentException( 450 org.opencms.db.Messages.get().container( 451 org.opencms.db.Messages.ERR_MODE_ENUM_PARSE_2, 452 new Integer(id), 453 CmsRelationType.class.getName())); 454 } 455 456 /** 457 * Parses an <code>String</code> into a relation type.<p> 458 * 459 * @param name the relation type name 460 * 461 * @return the enumeration element 462 * 463 * @throws CmsIllegalArgumentException if the given value could not be matched against a 464 * <code>{@link CmsRelationType}</code> object 465 * 466 * @see #valueOfXml(String) 467 * @see #valueOfJsp(String) 468 */ 469 public static CmsRelationType valueOf(String name) throws CmsIllegalArgumentException { 470 471 CmsRelationType result = valueOfInternal(name); 472 if (result == null) { 473 // no type found 474 throw new CmsIllegalArgumentException( 475 org.opencms.db.Messages.get().container( 476 org.opencms.db.Messages.ERR_MODE_ENUM_PARSE_2, 477 name, 478 CmsRelationType.class.getName())); 479 } 480 return result; 481 } 482 483 /** 484 * Parses the given value into a valid enumeration element for a JSP relation type.<p> 485 * 486 * This should be used to extend Strings like "weak" or "strong" to full relation type descriptors 487 * for JSP pages like "JSP_WEAK" or "JSP_STRONG".<p> 488 * 489 * @param name the name to get the JSP type for 490 * 491 * @return the JSP enumeration element 492 * 493 * @see #valueOf(String) 494 */ 495 public static CmsRelationType valueOfJsp(String name) { 496 497 CmsRelationType result = valueOfInternal(name); 498 if (result == null) { 499 result = valueOf(PREFIX_JSP + name); 500 } 501 return result; 502 } 503 504 /** 505 * Parses the given value into a valid enumeration element for a XML relation type.<p> 506 * 507 * This should be used to extend Strings like "weak" or "strong" to full relation type descriptors 508 * for XML documents like "XML_WEAK" or "XML_STRONG".<p> 509 * 510 * @param name the name to get the XML type for 511 * 512 * @return the XML enumeration element 513 * 514 * @see #valueOf(String) 515 */ 516 public static CmsRelationType valueOfXml(String name) { 517 518 CmsRelationType result = valueOfInternal(name); 519 if (result == null) { 520 result = valueOf(PREFIX_XML + name); 521 } 522 return result; 523 } 524 525 /** 526 * Internal parse method.<p> 527 * 528 * @param name the type to parse 529 * 530 * @return the enumeration element, or <code>null</code> if no matching element is found 531 */ 532 private static CmsRelationType valueOfInternal(String name) { 533 534 if (name != null) { 535 String valueUp = name.toUpperCase(); 536 for (int i = 0; i < VALUE_ARRAY.length; i++) { 537 if (valueUp.equals(VALUE_ARRAY[i].m_name)) { 538 return VALUE_ARRAY[i]; 539 } 540 } 541 // deprecated types 542 if (valueUp.equals("REFERENCE") || valueUp.equals("XML_REFERENCE")) { 543 return XML_WEAK; 544 } else if (valueUp.equals("ATTACHMENT") || valueUp.equals("XML_ATTACHMENT")) { 545 return XML_STRONG; 546 } 547 // user defined 548 for (int i = 0; i < getAllUserDefined().size(); i++) { 549 CmsRelationType type = getAllUserDefined().get(i); 550 if (valueUp.equals(type.m_name)) { 551 return type; 552 } 553 } 554 } 555 return null; 556 } 557 558 /** 559 * @see java.lang.Object#equals(java.lang.Object) 560 */ 561 @Override 562 public boolean equals(Object obj) { 563 564 if (this == obj) { 565 return true; 566 } 567 if (obj instanceof CmsRelationType) { 568 return (m_id == ((CmsRelationType)obj).m_id); 569 } 570 return false; 571 } 572 573 /** 574 * Gets the 'copy behavior' of the relation type, which is how relations of a resource should be handled when copying that resource.<p> 575 * 576 * @return the copy behavior of the relation type 577 */ 578 public CopyBehavior getCopyBehavior() { 579 580 return m_copyBehavior; 581 } 582 583 /** 584 * Returns the internal representation of this type.<p> 585 * 586 * @return the internal representation of this type 587 */ 588 public int getId() { 589 590 return m_id; 591 } 592 593 /** 594 * Returns a localized name for the given relation type.<p> 595 * 596 * @param messages the message bundle to use to resolve the name 597 * 598 * @return a localized name 599 */ 600 public String getLocalizedName(CmsMessages messages) { 601 602 String nameKey = "GUI_RELATION_TYPE_" + getName() + "_0"; 603 return messages.key(nameKey); 604 } 605 606 /** 607 * Returns a localized name for the given relation type.<p> 608 * 609 * @param locale the locale 610 * 611 * @return a localized name 612 */ 613 public String getLocalizedName(Locale locale) { 614 615 return getLocalizedName(Messages.get().getBundle(locale)); 616 } 617 618 /** 619 * Returns the type name.<p> 620 * 621 * @return the type name 622 * 623 * @see CmsRelationType#valueOf(String) 624 */ 625 public String getName() { 626 627 return m_name; 628 } 629 630 /** 631 * Returns the type name for xml output.<p> 632 * 633 * The short type name of XML or JSP types is only <code>"WEAK"</code> or <code>"STRONG"</code>. 634 * For other types the short name is equal to the name.<p> 635 * 636 * In case you need the full type name, use {@link #getName()}.<p> 637 * 638 * @return the short type name 639 * 640 * @see #getName() 641 * @see CmsRelationType#valueOfJsp(String) 642 * @see CmsRelationType#valueOfXml(String) 643 */ 644 public String getNameForXml() { 645 646 String result; 647 switch (getId()) { 648 case 3: // xml strong 649 result = VALUE_STRONG; 650 break; 651 case 4: // xml weak 652 result = VALUE_WEAK; 653 break; 654 case 5: // jsp strong 655 result = VALUE_STRONG; 656 break; 657 case 6: // jsp weak 658 result = VALUE_WEAK; 659 break; 660 default: 661 result = getName(); 662 } 663 return result; 664 } 665 666 /** 667 * Returns the string strong or weak.<p> 668 * 669 * @return the string strong or weak 670 * 671 * @see #isStrong() 672 */ 673 public String getType() { 674 675 return isStrong() ? VALUE_STRONG : VALUE_WEAK; 676 } 677 678 /** 679 * @see java.lang.Object#hashCode() 680 */ 681 @Override 682 public int hashCode() { 683 684 return m_id; 685 } 686 687 /** 688 * Checks if this relation type is defined in the content of a resource or not.<p> 689 * 690 * @return <code>true</code> if this relation type is defined in the content of a resource 691 */ 692 public boolean isDefinedInContent() { 693 694 return m_defInContent; 695 } 696 697 /** 698 * Checks if this is an internal relation type.<p> 699 * 700 * @return <code>true</code> if this is an internal relation type 701 */ 702 public boolean isInternal() { 703 704 return (getId() < USER_DEFINED_MODE_LIMIT); 705 } 706 707 /** 708 * Checks if the relation type is strong or weak.<p> 709 * 710 * @return <code>true</code> if the relation type is strong 711 */ 712 public boolean isStrong() { 713 714 return m_strong; 715 } 716 717 /** 718 * @see java.lang.Object#toString() 719 */ 720 @Override 721 public String toString() { 722 723 return m_name; 724 } 725}