📄 cmsxmlcontentdefinition.java
字号:
CmsXmlNestedContentDefinition cd = new CmsXmlNestedContentDefinition(null, typeName, minOccurs, maxOccurs);
sequence.add(cd);
}
// return a data structure with the collected values
return definition.new CmsXmlComplexTypeSequence(name, sequence, hasLanguageAttribute);
}
/**
* Looks up the given XML content definition system id in the internal content definition cache.<p>
*
* @param schemaLocation the system id of the XML content definition to look up
* @param resolver the XML entitiy resolver to use (contains the cache)
*
* @return the XML content definition found, or null if no definition is cached for the given system id
*/
private static CmsXmlContentDefinition getCachedContentDefinition(String schemaLocation, EntityResolver resolver) {
if (resolver instanceof CmsXmlEntityResolver) {
// check for a cached version of this content definition
CmsXmlEntityResolver cmsResolver = (CmsXmlEntityResolver)resolver;
return cmsResolver.getCachedContentDefinition(schemaLocation);
}
return null;
}
/**
* Internal method to unmarshal (read) a XML content definition instance from a XML document.<p>
*
* It is assumed that the XML content definition cache has already been tested and the document
* has not been found in the cache. After the XML content definition has been successfully created,
* it is placed in the cache.<p>
*
* @param document the XML document to generate a XML content definition from
* @param schemaLocation the location from which the XML schema was read (system id)
* @param resolver the XML entitiy resolver used by the given XML document
*
* @return a XML content definition instance unmarshalled from the XML document
*
* @throws CmsXmlException if something goes wrong
*/
private static CmsXmlContentDefinition unmarshalInternal(
Document document,
String schemaLocation,
EntityResolver resolver) throws CmsXmlException {
// analyze the document and generate the XML content type definition
Element root = document.getRootElement();
if (!XSD_NODE_SCHEMA.equals(root.getQName())) {
// schema node is required
throw new CmsXmlException(Messages.get().container(Messages.ERR_CD_NO_SCHEMA_NODE_0));
}
List includes = root.elements(XSD_NODE_INCLUDE);
if (includes.size() < 1) {
// one include is required
throw new CmsXmlException(Messages.get().container(Messages.ERR_CD_ONE_INCLUDE_REQUIRED_0));
}
Element include = (Element)includes.get(0);
String target = validateAttribute(include, XSD_ATTRIBUTE_SCHEMA_LOCATION, null);
if (!XSD_INCLUDE_OPENCMS.equals(target)) {
// the first include must point to the default OpenCms standard schema include
throw new CmsXmlException(Messages.get().container(
Messages.ERR_CD_FIRST_INCLUDE_2,
XSD_INCLUDE_OPENCMS,
target));
}
Set nestedDefinitions = new HashSet();
if (includes.size() > 1) {
// resolve additional, nested include calls
for (int i = 1; i < includes.size(); i++) {
Element inc = (Element)includes.get(i);
String schemaLoc = validateAttribute(inc, XSD_ATTRIBUTE_SCHEMA_LOCATION, null);
InputSource source = null;
try {
source = resolver.resolveEntity(null, schemaLoc);
} catch (Exception e) {
throw new CmsXmlException(Messages.get().container(Messages.ERR_CD_BAD_INCLUDE_1, schemaLoc));
}
CmsXmlContentDefinition xmlContentDefinition = unmarshal(source, schemaLoc, resolver);
nestedDefinitions.add(xmlContentDefinition);
}
}
List elements = root.elements(XSD_NODE_ELEMENT);
if (elements.size() != 1) {
// only one root element is allowed
throw new CmsXmlException(Messages.get().container(
Messages.ERR_CD_ROOT_ELEMENT_COUNT_1,
XSD_INCLUDE_OPENCMS,
new Integer(elements.size())));
}
// collect the data from the root element node
Element main = (Element)elements.get(0);
String name = validateAttribute(main, XSD_ATTRIBUTE_NAME, null);
// now process the complex types
List complexTypes = root.elements(XSD_NODE_COMPLEXTYPE);
if (complexTypes.size() != 2) {
// exactly two complex types are required
throw new CmsXmlException(Messages.get().container(
Messages.ERR_CD_COMPLEX_TYPE_COUNT_1,
new Integer(complexTypes.size())));
}
// generate the result XML content definition
CmsXmlContentDefinition result = new CmsXmlContentDefinition(name, null, schemaLocation);
// set the nested definitions
result.m_includes = nestedDefinitions;
List complexTypeData = new ArrayList();
Iterator ct = complexTypes.iterator();
while (ct.hasNext()) {
Element e = (Element)ct.next();
CmsXmlComplexTypeSequence sequence = validateComplexTypeSequence(e, nestedDefinitions, result);
complexTypeData.add(sequence);
}
// get the outer element sequence, this must be the first element
CmsXmlComplexTypeSequence outerSequence = (CmsXmlComplexTypeSequence)complexTypeData.get(0);
CmsXmlNestedContentDefinition outer = (CmsXmlNestedContentDefinition)outerSequence.m_sequence.get(0);
// make sure the inner and outer element names are as required
String outerTypeName = createTypeName(name);
String innerTypeName = createTypeName(outer.getName());
validateAttribute((Element)complexTypes.get(0), XSD_ATTRIBUTE_NAME, outerTypeName);
validateAttribute((Element)complexTypes.get(1), XSD_ATTRIBUTE_NAME, innerTypeName);
validateAttribute(main, XSD_ATTRIBUTE_TYPE, outerTypeName);
// the inner name is the element name set in the outer sequence
result.setInnerName(outer.getName());
// get the inner element sequence, this must be the second element
CmsXmlComplexTypeSequence innerSequence = (CmsXmlComplexTypeSequence)complexTypeData.get(1);
// add the types from the main sequence node
Iterator it = innerSequence.m_sequence.iterator();
while (it.hasNext()) {
result.addType((I_CmsXmlSchemaType)it.next());
}
// resolve the XML content handler information
List annotations = root.elements(XSD_NODE_ANNOTATION);
I_CmsXmlContentHandler contentHandler = null;
Element appInfoElement = null;
if (annotations.size() > 0) {
List appinfos = ((Element)annotations.get(0)).elements(XSD_NODE_APPINFO);
if (appinfos.size() > 0) {
// the first appinfo node contains the specific XML content data
appInfoElement = (Element)appinfos.get(0);
// check for a special content handler in the appinfo node
Element handlerElement = appInfoElement.element("handler");
if (handlerElement != null) {
String className = handlerElement.attributeValue("class");
if (className != null) {
contentHandler = OpenCms.getXmlContentTypeManager().getContentHandler(className, schemaLocation);
}
}
}
}
if (contentHandler == null) {
// if no content handler is defined, the default handler is used
contentHandler = OpenCms.getXmlContentTypeManager().getContentHandler(
CmsDefaultXmlContentHandler.class.getName(),
name);
}
// analyze the app info node with the selected XML content handler
contentHandler.initialize(appInfoElement, result);
result.m_contentHandler = contentHandler;
result.freeze();
if (resolver instanceof CmsXmlEntityResolver) {
// put the generated content definition in the cache
((CmsXmlEntityResolver)resolver).cacheContentDefinition(schemaLocation, result);
}
return result;
}
/**
* Adds the missing default XML according to this content definition to the given document element.<p>
*
* In case the root element already contains subnodes, only missing subnodes are added.<p>
*
* @param cms the current users OpenCms context
* @param document the document where the XML is added in (required for default XML generation)
* @param root the root node to add the missing XML for
* @param locale the locale to add the XML for
*
* @return the given root element with the missing content added
*/
public Element addDefaultXml(CmsObject cms, I_CmsXmlDocument document, Element root, Locale locale) {
Iterator i = m_typeSequence.iterator();
int currentPos = 0;
List allElements = root.elements();
while (i.hasNext()) {
I_CmsXmlSchemaType type = (I_CmsXmlSchemaType)i.next();
// check how many elements of this type already exist in the XML
String elementName = type.getName();
List elements = root.elements(elementName);
currentPos += elements.size();
for (int j = elements.size(); j < type.getMinOccurs(); j++) {
// append the missing elements
Element typeElement = type.generateXml(cms, document, root, locale);
// need to check for default value again because the of appinfo "mappings" node
I_CmsXmlContentValue value = type.createValue(document, typeElement, locale);
String defaultValue = document.getContentDefinition().getContentHandler().getDefault(cms, value, locale);
if (defaultValue != null) {
// only if there is a default value available use it to overwrite the initial default
value.setStringValue(cms, defaultValue);
}
// re-sort elements as they have been appended to the end of the XML root, not at the correct position
typeElement.detach();
allElements.add(currentPos, typeElement);
currentPos++;
}
}
return root;
}
/**
* Adds a nested (included) XML content definition.<p>
*
* @param nestedSchema the nested (included) XML content definition to add
*/
public void addInclude(CmsXmlContentDefinition nestedSchema) {
m_includes.add(nestedSchema);
}
/**
* Adds the given content type.<p>
*
* @param type the content type to add
*
* @throws CmsXmlException in case an unregisterd type is added
*/
public void addType(I_CmsXmlSchemaType type) throws CmsXmlException {
// check if the type to add actually exists in the type manager
CmsXmlContentTypeManager typeManager = OpenCms.getXmlContentTypeManager();
if (type.isSimpleType() && (typeManager.getContentType(type.getTypeName()) == null)) {
throw new CmsXmlException(Messages.get().container(Messages.ERR_UNREGISTERED_TYPE_1, type.getTypeName()));
}
// add the type to the internal type sequence and lookup table
m_typeSequence.add(type);
m_types.put(type.getName(), type);
// store reference to the content definition in the type
type.setContentDefinition(this);
}
/**
* Creates a clone of this XML content definition.<p>
*
* @return a clone of this XML content definition
*/
public Object clone() {
CmsXmlContentDefinition result = new CmsXmlContentDefinition();
result.m_innerName = m_innerName;
result.m_schemaLocation = m_schemaLocation;
result.m_typeSequence = m_typeSequence;
result.m_types = m_types;
result.m_contentHandler = m_contentHandler;
result.m_typeName = m_typeName;
result.m_includes = m_includes;
return result;
}
/**
* Generates the default XML content for this content definition, and append it to the given root element.<p>
*
* Please note: The default values for the annotations are read from the content definition of the given
* document. For a nested content definitions, this means that all defaults are set in the annotations of the
* "outer" or "main" content defintition.<p>
*
* @param cms the current users OpenCms context
* @param document the OpenCms XML document the XML is created for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -