/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/metaobj/trunk/metaobj-impl/api-impl/src/java/org/sakaiproject/metaobj/utils/xml/impl/BaseElementType.java $ * $Id: BaseElementType.java 105079 2012-02-24 23:08:11Z ottenhoff@longsight.com $ *********************************************************************************** * * Copyright (c) 2004, 2005, 2006, 2008 The Sakai Foundation * * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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 org.sakaiproject.metaobj.utils.xml.impl; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; import org.jdom.Attribute; import org.jdom.Element; import org.jdom.Namespace; import org.sakaiproject.metaobj.utils.xml.ElementType; import org.sakaiproject.metaobj.utils.xml.NormalizationException; import org.sakaiproject.metaobj.utils.xml.SchemaNode; import org.sakaiproject.metaobj.utils.xml.ValidatedNode; import org.sakaiproject.metaobj.utils.xml.ValidationError; import org.sakaiproject.metaobj.utils.xml.ValueRange; import org.sakaiproject.util.FormattedText; /** * Created by IntelliJ IDEA. * User: John Ellis * Date: Apr 15, 2004 * Time: 5:07:44 PM * To change this template use File | Settings | File Templates. */ public class BaseElementType implements ElementType { protected static final int WHITE_SPACE_TYPE_NONE = 0; protected static final int WHITE_SPACE_TYPE_PRESERVE = 1; // replace with spaces protected static final int WHITE_SPACE_TYPE_REPLACE = 2; // remove all whitespace and replace with spaces protected static final int WHITE_SPACE_TYPE_COLLAPSE = 3; protected int length = -1; protected int maxLength = -1; protected int minLength = -1; protected Pattern pattern = null; protected int whiteSpaceType = WHITE_SPACE_TYPE_NONE; protected String defaultValue = ""; protected String fixedValue = ""; protected Element schemaElement; protected SchemaNode parentNode = null; private List enumeration = null; private String baseType; private boolean richText = false; public BaseElementType(String typeName, Element schemaElement, SchemaNode parentNode, Namespace xsdNamespace) { setBaseType(typeName); this.schemaElement = schemaElement; this.parentNode = parentNode; init(xsdNamespace); } protected void init(Namespace xsdNamespace) { Element simpleType = schemaElement.getChild("simpleType", xsdNamespace); if (simpleType != null) { Element restrictions = simpleType.getChild("restriction", xsdNamespace); if (restrictions != null) { // process restrictions length = processIntRestriction(restrictions, "length", xsdNamespace, length); maxLength = processIntRestriction(restrictions, "maxLength", xsdNamespace, maxLength); minLength = processIntRestriction(restrictions, "minLength", xsdNamespace, minLength); String patternValue = processStringRestriction(restrictions, "pattern", xsdNamespace); if (patternValue != null) { pattern = Pattern.compile(patternValue); } String whiteSpaceValue = processStringRestriction(restrictions, "whiteSpace", xsdNamespace); if (whiteSpaceValue != null) { if (whiteSpaceValue.equals("preserve")) { whiteSpaceType = WHITE_SPACE_TYPE_PRESERVE; } if (whiteSpaceValue.equals("replace")) { whiteSpaceType = WHITE_SPACE_TYPE_REPLACE; } if (whiteSpaceValue.equals("collapse")) { whiteSpaceType = WHITE_SPACE_TYPE_COLLAPSE; } } } } if (schemaElement.getAttribute("default") != null) { defaultValue = schemaElement.getAttributeValue("default"); } if (schemaElement.getAttribute("fixed") != null) { fixedValue = schemaElement.getAttributeValue("fixed"); defaultValue = fixedValue; } if (parentNode.getDocumentAnnotation("ospi.isRichText") != null || parentNode.getDocumentAnnotation("sakai.isRichText") != null) { richText = true; } } protected void processEnumerations(Element restrictions, Namespace xsdNamespace) { List enums = restrictions.getChildren("enumeration", xsdNamespace); List temp = null; enumeration = null; if (enums.size() > 0) { temp = new ArrayList(); } for (Iterator i = enums.iterator(); i.hasNext();) { Element enumer = (Element) i.next(); String value = enumer.getAttributeValue("value"); temp.add(getActualNormalizedValue(value)); } enumeration = temp; } protected String processStringRestriction(Element restrictions, String s, Namespace xsdNamespace) { Element currentRestriction = restrictions.getChild(s, xsdNamespace); if (currentRestriction == null) { return null; } return currentRestriction.getAttributeValue("value"); } protected int processIntRestriction(Element restrictions, String s, Namespace xsdNamespace, int defaultValue) { String value = processStringRestriction(restrictions, s, xsdNamespace); if (value == null) { return defaultValue; } return Integer.parseInt(value); } /** * Validates the passed in node and all children. * Will also normalize any values. * * @param node a jdom element to validate * @return the validated Element wrapped * in a ValidatedNode class */ public ValidatedNode validateAndNormalize(Element node) { ValidatedNodeImpl validatedNode = new ValidatedNodeImpl(parentNode, node); String value = node.getText(); try { value = getSchemaNormalizedValue(value); node.setText(value); validatedNode.setNormalizedValue(getActualNormalizedValue(value)); if (value == null || value.length() == 0) { return null; } } catch (NormalizationException exp) { validatedNode.getErrors().add(new ValidationError(validatedNode, exp.getErrorCode(), exp.getErrorInfo())); } return validatedNode; } public String getSchemaNormalizedValue(Object value) throws NormalizationException { if (value == null) { return null; } return getSchemaNormalizedValue(value.toString()); } public String getSchemaNormalizedValue(String value) throws NormalizationException { if (value == null) { return defaultValue; } if (fixedValue != null && fixedValue.length() > 0) { return fixedValue; } String startingValue = handleWhiteSpace(value.toString()); int valueLength = startingValue.length(); if (richText) { StringBuilder errors = new StringBuilder(); String newValue = FormattedText.processFormattedText(startingValue, errors); if (errors.length() > 0) { throw new NormalizationException(errors.toString(), NormalizationException.RICH_TEXT_FORMAT_PASSTHROUGH, new Object[]{errors.toString()}); } else { startingValue = newValue; } } if (length != -1 && valueLength != length) { throw new NormalizationException("Invalid string length", NormalizationException.INVALID_LENGTH_ERROR_CODE, new Object[]{startingValue, new Integer(length)}); } if (maxLength != -1 && valueLength > maxLength) { /* * SAK-12670 - error description is too long bc * the field value is too long. This clips off the * value of the field to only 100 chars */ String val = startingValue; if(startingValue.length() > 100){ val = val.substring(0, 100) + "..."; } throw new NormalizationException("Invalid string length", NormalizationException.INVALID_LENGTH_TOO_LONG_ERROR_CODE, new Object[]{val, new Integer(maxLength)}); } if (minLength != -1 && valueLength < minLength && minLength == 1) { throw new NormalizationException("Required field", NormalizationException.REQIRED_FIELD_ERROR_CODE, new Object[0]); } if (minLength != -1 && valueLength < minLength) { throw new NormalizationException("Invalid string length", NormalizationException.INVALID_LENGTH_TOO_SHORT_ERROR_CODE, new Object[]{startingValue, new Integer(minLength)}); } if (pattern != null && !pattern.matcher(startingValue).matches()) { throw new NormalizationException("Invalid string pattern", NormalizationException.INVALID_PATTERN_MATCH_ERROR_CODE, new Object[]{startingValue, pattern.pattern()}); } return startingValue; } private String handleWhiteSpace(String s) { if (whiteSpaceType == WHITE_SPACE_TYPE_NONE || whiteSpaceType == WHITE_SPACE_TYPE_PRESERVE) { return s; } if (whiteSpaceType == WHITE_SPACE_TYPE_REPLACE) { s = s.replaceAll("\\s", " "); } else if (whiteSpaceType == WHITE_SPACE_TYPE_COLLAPSE) { s = s.replaceAll("\\s+", " "); } return s; } public Class getObjectType() { return String.class; } public Object getActualNormalizedValue(String value) { Object returned = getSchemaNormalizedValue(value); if (enumeration != null) { if (!enumeration.contains(returned)) { throw new NormalizationException("Not enumerated", NormalizationException.NOT_IN_ENUMERATION_ERROR_CODE, new Object[]{returned}); } } return returned; } public int getLength() { return length; } public int getMaxLength() { return maxLength; } public int getMinLength() { return minLength; } public Pattern getPattern() { return pattern; } public ValueRange getRange() { return null; } public int getWhiteSpaceType() { return whiteSpaceType; } public String getDefaultValue() { return defaultValue; } public String getFixedValue() { return fixedValue; } public List getEnumeration() { return enumeration; } public BaseElementType postInit(Namespace xsdNamespace) { Element simpleType = schemaElement.getChild("simpleType", xsdNamespace); if (simpleType != null) { Element restrictions = simpleType.getChild("restriction", xsdNamespace); if (restrictions != null) { processEnumerations(restrictions, xsdNamespace); } } return this; } public ValidatedNode validateAndNormalize(Attribute node) { ValidatedNodeImpl validatedNode = new ValidatedNodeImpl(parentNode, null); String value = node.getValue(); try { value = getSchemaNormalizedValue(value); node.setValue(value); validatedNode.setNormalizedValue(getActualNormalizedValue(value)); if (value == null || value.length() == 0) { return null; } } catch (NormalizationException exp) { validatedNode.getErrors().add(new ValidationError(validatedNode, exp.getErrorCode(), exp.getErrorInfo())); } return validatedNode; } public String getBaseType() { return baseType; } public void setBaseType(String baseType) { this.baseType = baseType; } }