diff --git a/ccm-cms/src/com/arsdigita/cms/ContentType.java b/ccm-cms/src/com/arsdigita/cms/ContentType.java index 8d21ef456..6e141c9c8 100755 --- a/ccm-cms/src/com/arsdigita/cms/ContentType.java +++ b/ccm-cms/src/com/arsdigita/cms/ContentType.java @@ -32,6 +32,9 @@ import com.arsdigita.persistence.OID; import com.arsdigita.persistence.SessionManager; import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.web.Web; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.math.BigDecimal; @@ -42,15 +45,22 @@ import java.util.ArrayList; import java.net.URL; import java.net.MalformedURLException; import java.util.StringTokenizer; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; import org.apache.log4j.Logger; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; /** - *
A Content Type defines the characteristics of a content item. Content - * management resources are registered to a content type, including - * the {@link com.arsdigita.cms.AuthoringKit Authoring Kit}, and - * {@link com.arsdigita.cms.Template templates}.
+ *+ * A Content Type defines the characteristics of a content item. Content management resources are + * registered to a content type, including the {@link com.arsdigita.cms.AuthoringKit Authoring Kit}, + * and {@link com.arsdigita.cms.Template templates}.
* - *Each content type is associated with a {@link + *
+ * Each content type is associated with a {@link * com.arsdigita.domain.DomainObject domain object} and a {@link * com.arsdigita.persistence.DataObject data object} type.
* @@ -60,26 +70,32 @@ import org.apache.log4j.Logger; */ public class ContentType extends ACSObject { - /** Internal logger instance to faciliate debugging. Enable logging output - * by editing /WEB-INF/conf/log4j.properties int hte runtime environment - * and set com.arsdigita.cms.ui.authoring.NewItemForm=DEBUG by uncommenting - * or adding the line. */ + /** + * Internal logger instance to faciliate debugging. Enable logging output by editing + * /WEB-INF/conf/log4j.properties int hte runtime environment and set + * com.arsdigita.cms.ui.authoring.NewItemForm=DEBUG by uncommenting or adding the line. + */ private static final Logger s_log = Logger.getLogger(ContentType.class); - public static final String BASE_DATA_OBJECT_TYPE = - "com.arsdigita.cms.ContentType"; - /** The path content types are expected to store their type definition - * file (usually [domainObjectBaseName].xml by convention). Any content - * item should use this location unless there are good reasons for a - * different location. */ - public static final String CONTENTTYPE_DEFINITIONFILE_PATH = - "/WEB-INF/content-types/"; + public static final String BASE_DATA_OBJECT_TYPE = "com.arsdigita.cms.ContentType"; + /** + * The path content types are expected to store their type definition file (usually + * [domainObjectBaseName].xml by convention). Any content item should use this location unless + * there are good reasons for a different location. + */ + public static final String CONTENTTYPE_DEFINITIONFILE_PATH = "/WEB-INF/content-types/"; public static final String OBJECT_TYPE = "associatedObjectType"; - /** The name or title of the content type, e.g. "File Storage Item" */ + /** + * The name or title of the content type, e.g. "File Storage Item" + */ public static final String LABEL = "label"; - /** A short description of the type, what is is meant to do / to use for. */ + /** + * A short description of the type, what is is meant to do / to use for. + */ public static final String DESCRIPTION = "description"; - /** Fully qualified name of the (main) domain class (and main entry point)*/ + /** + * Fully qualified name of the (main) domain class (and main entry point) + */ public static final String CLASSNAME = "className"; public static final String MODE = "mode"; public static final String AUTHORING_KIT = "authoringKit"; @@ -90,32 +106,31 @@ public class ContentType extends ACSObject { /** * Default constructor. This creates a new folder. - **/ + * + */ public ContentType() { super(BASE_DATA_OBJECT_TYPE); } /** - * Constructor. The containedDataObject is retrieved
- * from the persistent storage mechanism with an OID
- * specified by oid.
+ * Constructor. The contained DataObject is retrieved from the persistent storage
+ * mechanism with an OID specified by oid.
*
- * @param oid The OID for the retrieved
- * DataObject.
- **/
+ * @param oid The OID for the retrieved DataObject.
+ *
+ */
public ContentType(OID oid) throws DataObjectNotFoundException {
super(oid);
}
/**
- * Constructor. The contained DataObject is retrieved
- * from the persistent storage mechanism with an OID
- * specified by id and
+ * Constructor. The contained DataObject is retrieved from the persistent storage
+ * mechanism with an OID specified by id and
* ContentType.BASE_DATA_OBJECT_TYPE.
*
- * @param id The id for the retrieved
- * DataObject.
- **/
+ * @param id The id for the retrieved DataObject.
+ *
+ */
public ContentType(BigDecimal id) throws DataObjectNotFoundException {
this(new OID(BASE_DATA_OBJECT_TYPE, id));
}
@@ -129,8 +144,8 @@ public class ContentType extends ACSObject {
}
/**
- * @return the base PDL object type for this item. Child classes should
- * override this method to return the correct value
+ * @return the base PDL object type for this item. Child classes should override this method to
+ * return the correct value
*/
@Override
public String getBaseDataObjectType() {
@@ -146,10 +161,9 @@ public class ContentType extends ACSObject {
}
/**
- * Returns the object type of the items of this content type. (For example:
- * If I create a ContentType "foo". Then a I create an item "bar"
- * of type foo. This associated object type is the same as
- * bar.getObjectType())
+ * Returns the object type of the items of this content type. (For example: If I create a
+ * ContentType "foo". Then a I create an item "bar" of type foo. This associated object type is
+ * the same as bar.getObjectType())
*
* @return The data object type representation of this content type
*/
@@ -165,96 +179,135 @@ public class ContentType extends ACSObject {
public void setAssociatedObjectType(String objType) {
set(OBJECT_TYPE, objType);
}
-
+
/**
- * Fetches the label for the content type. The label is a globalized
- * notation displayed to the user to identify the content type. As an
- * example a content type named "Article" (as in getName()) will be
- * displayed in an english environment as the label "Article", in
- * German as "Artikel", etc.
- *
- * The label is retrieved from content type's resources. The message uses
- * some convention to retrieve the message key and resource bundle.
- *
- * Client classes may overwrite the method to provide a label from a
- * diffrent source.
- *
+ * Fetches the label for the content type. The label is a globalized notation displayed to the
+ * user to identify the content type. As an example a content type named "Article" (as in
+ * getName()) will be displayed in an english environment as the label "Article", in German as
+ * "Artikel", etc.
+ *
+ * The label is retrieved from content type's resources. The message uses some convention to
+ * retrieve the message key and resource bundle.
+ *
+ * Client classes may overwrite the method to provide a label from a different source.
+ *
* @return The (globalized) label.
*/
public GlobalizedMessage getLabel() {
-
+
GlobalizedMessage label; // the the type's label to return
// We assume the name of the ObjectType is the base for various
// resources we need so we determine it first.
- String objectTypeName = getAssociatedObjectType();
- if (s_log.isDebugEnabled()) {
- s_log.debug(
- "Object Type is " + objectTypeName );
- }
+ String objectTypeName = getAssociatedObjectType();
+ if (s_log.isDebugEnabled()) {
+ s_log.debug(
+ "Object Type is " + objectTypeName);
+ }
// First we'll try to locate the resource file assuming it is named
// as the object type with resources.properties appended.
- String bundleResourcePath = "/".concat(objectTypeName.replace(".","/"))
- .concat("Resources.properties");
- if (s_log.isDebugEnabled()) {
- s_log.debug("resource path is " + bundleResourcePath );
- }
+ String bundleResourcePath = "/".concat(objectTypeName.replace(".", "/"))
+ .concat("Resources.properties");
+ if (s_log.isDebugEnabled()) {
+ s_log.debug("resource path is " + bundleResourcePath);
+ }
// Alternatively we may try the content item's definition file. Just
// guessing its name here.
- String typeResourcePath = CONTENTTYPE_DEFINITIONFILE_PATH
- .concat(objectTypeName.replace(".","/"))
- .concat(".xml");
+ String typeResourcePath = CONTENTTYPE_DEFINITIONFILE_PATH
+ .concat(objectTypeName.replace(".", "/"))
+ .concat(".xml");
// We assume the name of the key in resource bundle is the same as
// the ObjectType minus the domain part ("com.arsdigita.")
// and starting with "cms" and suffix ".type_label" appended
String labelKey = objectTypeName.substring(objectTypeName.indexOf("cms"))
- .concat(".type_label")
- .toLowerCase();
+ .concat(".type_label")
+ .toLowerCase();
// First try: check, if the resource file really exists, and if it does,
// use it.
- if (this.getClass().getClassLoader().getResource(bundleResourcePath)!=null) {
+ if (this.getClass().getClassLoader().getResource(bundleResourcePath) != null) {
// Property file exists, use it!
- String bundleName = objectTypeName.concat("Resources");
+ final String bundleName = objectTypeName.concat("Resources");
// Create the globalized label
label = new GlobalizedMessage(labelKey, bundleName);
} else {
- // No property file found, try to use the item's definition file
- if (this.getClass().getClassLoader()
- .getResource(typeResourcePath)!=null) {
- // item definition file found. use it's
- // determine the bundle from attribute "descriptionBundle"
- // which should provide an item specific description (but
- // unfortunately due to lazy programmers not always does).
- // As a proper example:
- // /WEB-INF/content-types/com.arsditita.cms.contenttypes.Event.xml
- String bundleName = "REPLACE ME"; // REPLACE ME!
+ final InputStream defFile = Thread.currentThread().getContextClassLoader()
+ .getResourceAsStream(typeResourcePath);
- label = new GlobalizedMessage(labelKey, bundleName);
-
- } else {
+ // No property file found, try to use the item's definition file
+ if (defFile == null) {
// Giving up!
-
+
// As a fall back use the (not globalized) "name" of the type as
// stored in the database to display the type to the user. Is is
// used as the "key" in a GloablizedMessage, which it is definitely
// not. But GlobalizedMessage displays the key if it could not be
// found in a resource file.
label = new GlobalizedMessage(getName());
+ } else {
+ // item definition file found. use it's
+ // determine the bundle from attribute "descriptionBundle"
+ // which should provide an item specific description (but
+ // unfortunately due to lazy programmers not always does).
+ // As a proper example:
+ // /WEB-INF/content-types/com.arsditita.cms.contenttypes.Event.xml
+
+ try {
+ final SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ final SAXParser parser = parserFactory.newSAXParser();
+ final BundleName bundleName = new BundleName();
+ parser.parse(defFile, bundleName);
+
+ //String bundleName = "REPLACE ME"; // REPLACE ME!
+ if (bundleName.getName() == null) {
+ return new GlobalizedMessage(getName());
+ } else {
+ label = new GlobalizedMessage(labelKey, bundleName.getName());
+ }
+ } catch (ParserConfigurationException ex) {
+ label = new GlobalizedMessage(getName());
+ } catch (SAXException ex) {
+ label = new GlobalizedMessage(getName());
+ } catch (IOException ex) {
+ label = new GlobalizedMessage(getName());
+ }
}
-
+
}
return label;
}
+ private class BundleName extends DefaultHandler {
+
+ private String name;
+
+ public BundleName() {
+ //Nothing
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public void startElement(final String namespaceURI,
+ final String localName,
+ final String qName,
+ final Attributes attributes) {
+ if ("ctd:authoring-step".equals(qName)) {
+ name = attributes.getValue("labelBundle");
+ }
+ }
+
+ }
+
/**
- * Fetches the name for the content type. The name is a fixed String, which
- * 'names' a content type and is not localizible. It is stored in the
- * database and a symbolic name for the formal ID. It may contain any
- * characters but is preferable an english term. Examples are "FAQ item" or
- * "Article" or "Multipart Article". It has to be unique system-wide.
+ * Fetches the name for the content type. The name is a fixed String, which 'names' a content
+ * type and is not localizible. It is stored in the database and a symbolic name for the formal
+ * ID. It may contain any characters but is preferable an english term. Examples are "FAQ item"
+ * or "Article" or "Multipart Article". It has to be unique system-wide.
*
* @return The name (ie. may be used as a non-localized label)
*/
@@ -264,11 +317,11 @@ public class ContentType extends ACSObject {
/**
* Sets the name for this content type. The name is a fixed String.
+ *
* @see getName() for additional details.
- *
- * The name is stored in the database. In the database this property is
- * stored under 'label', when globliation was not an issue.
- * The Method is primarly used in the initial loading step.
+ *
+ * The name is stored in the database. In the database this property is stored under 'label',
+ * when globliation was not an issue. The Method is primarly used in the initial loading step.
*
* @param name The name
*/
@@ -313,36 +366,32 @@ public class ContentType extends ACSObject {
}
/**
- * An internal content type is one that is not user-defined and maintained - * internally. A content type should be made internal under the following - * two conditions:
+ *+ * An internal content type is one that is not user-defined and maintained internally. A content + * type should be made internal under the following two conditions:
* *The {@link com.arsdigita.cms.Template} content type is one such - * internal content type.
+ *+ * The {@link com.arsdigita.cms.Template} content type is one such internal content type.
* - * @return Boolean.TRUE if this content type is internal, Boolean.FALSE - * otherwise. + * @return Boolean.TRUE if this content type is internal, Boolean.FALSE otherwise. */ public Boolean isInternal() { return "I".equalsIgnoreCase((String) get(MODE)); } /** - *A hidden content type is one that is not user-defined but not meant - * to be used directly (p. ex. GenericArticle). in contrast they provide - * some basic features for different kind of content type to be extended - * from. Also, they are legit perents for UDCTs. + *
+ * A hidden content type is one that is not user-defined but not meant to be used directly (p.
+ * ex. GenericArticle). in contrast they provide some basic features for different kind of
+ * content type to be extended from. Also, they are legit perents for UDCTs.
*
- * @return Boolean.TRUE if this content type is internal, Boolean.FALSE
- * otherwise.
+ * @return Boolean.TRUE if this content type is internal, Boolean.FALSE otherwise.
*/
public Boolean isHidden() {
return "H".equalsIgnoreCase((String) get(MODE));
@@ -380,21 +429,18 @@ public class ContentType extends ACSObject {
}
/**
- * Create an authoring kit to this content type. To save this authoring
- * kit, you need to call save() method on the
- * returned AuthoringKit.
+ * Create an authoring kit to this content type. To save this authoring kit, you need to call
+ * save() method on the returned AuthoringKit.
*/
public AuthoringKit createAuthoringKit() {
return createAuthoringKit(null);
}
/**
- * Create an authoring kit to this content type. To save this authoring
- * kit, you need to call save() method on the
- * returned AuthoringKit.
+ * Create an authoring kit to this content type. To save this authoring kit, you need to call
+ * save() method on the returned AuthoringKit.
*
- * @param createComponent the create component class associated with
- * the authoring kit
+ * @param createComponent the create component class associated with the authoring kit
*/
public AuthoringKit createAuthoringKit(String createComponent) {
@@ -407,27 +453,25 @@ public class ContentType extends ACSObject {
return kit;
} else {
throw new RuntimeException(
- "An AuthorigKit exists for this ContentType.");
+ "An AuthorigKit exists for this ContentType.");
}
}
/**
- * Fetch the item creation form id of the Java domain object implementation.
- * applies to user-defined types
+ * Fetch the item creation form id of the Java domain object implementation. applies to
+ * user-defined types
*
- * @return The id of the persistent form used to create an item
- * of this content type
+ * @return The id of the persistent form used to create an item of this content type
*/
public BigDecimal getItemFormID() {
return (BigDecimal) get(ITEM_FORM_ID);
}
/**
- * Sets the item creation form id of the Java domain object implementation.
- * applies to user-defined types
+ * Sets the item creation form id of the Java domain object implementation. applies to
+ * user-defined types
*
- * @param itemFormID The id of the persistent form used to create an item
- * of this content type
+ * @param itemFormID The id of the persistent form used to create an item of this content type
*/
public void setItemFormID(BigDecimal itemFormID) {
set(ITEM_FORM_ID, itemFormID);
@@ -436,8 +480,8 @@ public class ContentType extends ACSObject {
/**
* Retrieve the persistent form of this content type
*
- * @return the persistent form used to create or edit content items
- * of this type (only applies to user-defined types)
+ * @return the persistent form used to create or edit content items of this type (only applies
+ * to user-defined types)
*/
public PersistentForm getItemForm() throws DataObjectNotFoundException {
@@ -452,7 +496,7 @@ public class ContentType extends ACSObject {
/**
* Add an ancestor to the list of descendants, if not already in the list.
- *
+ *
* @param newAncestor ID of the ancestor to add
*/
public void addAncestor(BigDecimal newAncestor) {
@@ -478,7 +522,7 @@ public class ContentType extends ACSObject {
/**
* Remove an ancestor id from the list of descendants.
- *
+ *
* @param ancestor ID to be removed
*/
public void delAncestor(BigDecimal ancestor) {
@@ -506,7 +550,7 @@ public class ContentType extends ACSObject {
/**
* Get the list of ancestors.
- *
+ *
* @return
*/
public String getAncestors() {
@@ -515,7 +559,7 @@ public class ContentType extends ACSObject {
/**
* Add a descendant to the list of descendants, if not already in list.
- *
+ *
* @param newDescendant ID of the descendant to add
*/
public void addDescendants(BigDecimal newDescendant) {
@@ -523,7 +567,7 @@ public class ContentType extends ACSObject {
if (getID().equals(newDescendant)) {
return;
}
-
+
// Get the list of descendants from db
String descendants = (String) get(DESCENDANTS);
@@ -547,6 +591,7 @@ public class ContentType extends ACSObject {
/**
* Get the list of descendants
+ *
* @return
*/
public String getDescendants() {
@@ -555,6 +600,7 @@ public class ContentType extends ACSObject {
/**
* Remove a descendant from the list of descendants
+ *
* @param descendant ID to be removed
*/
public void delDescendants(BigDecimal descendant) {
@@ -585,36 +631,35 @@ public class ContentType extends ACSObject {
// Fetching/Finding content types.
//
//////////////////////////////////////
-
/**
* Find the content type with the associated with the object type.
*
* @param objType The fully-qualified name of the data object type
+ *
* @return The content type associated with the object type
*/
public static ContentType findByAssociatedObjectType(String objType)
- throws DataObjectNotFoundException {
-
+ throws DataObjectNotFoundException {
+
ContentTypeCollection types = getAllContentTypes();
types.addFilter("associatedObjectType = :type").set("type", objType);
if (types.next()) {
ContentType type = types.getContentType();
types.close();
-
+
return type;
} else {
// no match
types.close();
throw new DataObjectNotFoundException(
- "No matching content type for object type " + objType);
+ "No matching content type for object type " + objType);
}
}
/**
- * Fetches a collection of all content types, including internal content
- * types.
+ * Fetches a collection of all content types, including internal content types.
*
* @return A collection of all content types
*/
@@ -623,11 +668,10 @@ public class ContentType extends ACSObject {
}
/**
- * Fetches a collection of all content types, including internal content
- * types.
+ * Fetches a collection of all content types, including internal content types.
+ *
+ * @param hidden If false, fetch all content types, ecluding hidden content types
*
- * @param hidden If false, fetch all content types, ecluding hidden
- * content types
* @return A collection of all content types
*/
public static ContentTypeCollection getAllContentTypes(boolean hidden) {
@@ -644,10 +688,8 @@ public class ContentType extends ACSObject {
}
/**
- * @param internal If false, fetch all content types, excluding internal
- * content types.
- * @param hidden If false, fetch all content types, excluding hidden
- * content types.
+ * @param internal If false, fetch all content types, excluding internal content types.
+ * @param hidden If false, fetch all content types, excluding hidden content types.
*/
private static ContentTypeCollection getAllContentTypes(boolean internal, boolean hidden) {
DataCollection da = SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE);
@@ -664,8 +706,8 @@ public class ContentType extends ACSObject {
}
/**
- * Fetches a collection of content types that have been registered
- * to at least one content section, excluding internal content types.
+ * Fetches a collection of content types that have been registered to at least one content
+ * section, excluding internal content types.
*
* @return A collection of registered content types
*/
@@ -677,9 +719,10 @@ public class ContentType extends ACSObject {
}
/**
- *
+ *
* @param ct
- * @return
+ *
+ * @return
*/
public static ContentTypeCollection getDescendantsOf(ContentType ct) {
ContentTypeCollection ctc = ContentType.getRegisteredContentTypes();
@@ -706,13 +749,12 @@ public class ContentType extends ACSObject {
ctc.addFilter(or);
return ctc;
}
-
+
private static List s_xsl = new ArrayList();
/**
- * Registers an XSL file against a content type.
- * NB this interface is liable to change.
- *
+ * Registers an XSL file against a content type. NB this interface is liable to change.
+ *
* @param type the content type
* @param path the path relative to the server root
*/
@@ -721,29 +763,27 @@ public class ContentType extends ACSObject {
}
/**
- * Unregisters an XSL file against a content type.
- * NB this interface is liable to change.
- *
+ * Unregisters an XSL file against a content type. NB this interface is liable to change.
+ *
* @param type the content type
* @param path the path relative to the server root
*/
public static void unregisterXSLFile(ContentType type,
- String path) {
+ String path) {
s_xsl.remove(new XSLEntry(type, path));
}
/**
- * Gets an iterator of java.net.URL objects for
- * all registered XSL files.
- *
- * @return
+ * Gets an iterator of java.net.URL objects for all registered XSL files.
+ *
+ * @return
*/
public static Iterator getXSLFileURLs() {
return new EntryIterator(s_xsl.iterator());
}
/**
- *
+ *
*/
private static class EntryIterator implements Iterator {
@@ -765,9 +805,9 @@ public class ContentType extends ACSObject {
try {
return new URL(Web.getConfig().getDefaultScheme(),
- Web.getConfig().getHost().getName(),
- Web.getConfig().getHost().getPort(),
- path);
+ Web.getConfig().getHost().getName(),
+ Web.getConfig().getHost().getPort(),
+ path);
} catch (MalformedURLException ex) {
throw new UncheckedWrapperException("path malformed" + path, ex);
}
@@ -777,10 +817,11 @@ public class ContentType extends ACSObject {
public void remove() {
m_inner.remove();
}
+
}
/**
- *
+ *
*/
private static class XSLEntry {
@@ -788,7 +829,7 @@ public class ContentType extends ACSObject {
private final String m_path;
public XSLEntry(ContentType type,
- String path) {
+ String path) {
m_type = type;
m_path = path;
}
@@ -808,12 +849,14 @@ public class ContentType extends ACSObject {
}
XSLEntry e = (XSLEntry) o;
return m_path.equals(e.m_path)
- && m_type.equals(e.m_type);
+ && m_type.equals(e.m_type);
}
@Override
public int hashCode() {
return m_path.hashCode() + m_type.hashCode();
}
+
}
+
}
diff --git a/ccm-sci-publications/src/WEB-INF/content-types/com/arsdigita/cms/contenttypes/ArticleInCollectedVolume.xml b/ccm-sci-publications/src/WEB-INF/content-types/com/arsdigita/cms/contenttypes/ArticleInCollectedVolume.xml
index 8610ceeee..945c84cd3 100644
--- a/ccm-sci-publications/src/WEB-INF/content-types/com/arsdigita/cms/contenttypes/ArticleInCollectedVolume.xml
+++ b/ccm-sci-publications/src/WEB-INF/content-types/com/arsdigita/cms/contenttypes/ArticleInCollectedVolume.xml
@@ -4,27 +4,27 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.redhat.com/cms/content-types content-types.xsd">
-