1 /* |
1 /* |
2 * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. |
3 * @LastModified: Sep 2017 |
3 * @LastModified: Oct 2017 |
4 */ |
4 */ |
5 /* |
5 /* |
6 * Licensed to the Apache Software Foundation (ASF) under one or more |
6 * Licensed to the Apache Software Foundation (ASF) under one or more |
7 * contributor license agreements. See the NOTICE file distributed with |
7 * contributor license agreements. See the NOTICE file distributed with |
8 * this work for additional information regarding copyright ownership. |
8 * this work for additional information regarding copyright ownership. |
81 import java.io.IOException; |
81 import java.io.IOException; |
82 import java.util.ArrayList; |
82 import java.util.ArrayList; |
83 import java.util.Collections; |
83 import java.util.Collections; |
84 import java.util.HashMap; |
84 import java.util.HashMap; |
85 import java.util.Iterator; |
85 import java.util.Iterator; |
|
86 import java.util.List; |
86 import java.util.Map; |
87 import java.util.Map; |
87 import java.util.Stack; |
88 import java.util.Stack; |
88 import java.util.Vector; |
89 import java.util.Vector; |
89 import javax.xml.XMLConstants; |
90 import javax.xml.XMLConstants; |
90 import jdk.xml.internal.JdkXmlUtils; |
91 import jdk.xml.internal.JdkXmlUtils; |
429 // the error reporter property |
430 // the error reporter property |
430 XMLErrorReporter fErrorReporter; |
431 XMLErrorReporter fErrorReporter; |
431 |
432 |
432 // store error codes; starting position of the errors for each element; |
433 // store error codes; starting position of the errors for each element; |
433 // number of element (depth); and whether to record error |
434 // number of element (depth); and whether to record error |
434 Vector fErrors = new Vector(); |
435 Vector<String> fErrors = new Vector<>(); |
435 int[] fContext = new int[INITIAL_STACK_SIZE]; |
436 int[] fContext = new int[INITIAL_STACK_SIZE]; |
436 int fContextCount; |
437 int fContextCount; |
437 |
438 |
438 // set the external error reporter, clear errors |
439 // set the external error reporter, clear errors |
439 public void reset(XMLErrorReporter errorReporter) { |
440 public void reset(XMLErrorReporter errorReporter) { |
472 if (size == 0) |
473 if (size == 0) |
473 return null; |
474 return null; |
474 // copy errors from the list to an string array |
475 // copy errors from the list to an string array |
475 String[] errors = new String[size]; |
476 String[] errors = new String[size]; |
476 for (int i = 0; i < size; i++) { |
477 for (int i = 0; i < size; i++) { |
477 errors[i] = (String) fErrors.elementAt(contextPos + i); |
478 errors[i] = fErrors.get(contextPos + i); |
478 } |
479 } |
479 // remove errors of the current element |
480 // remove errors of the current element |
480 fErrors.setSize(contextPos); |
481 fErrors.setSize(contextPos); |
481 return errors; |
482 return errors; |
482 } |
483 } |
496 if (size == 0) |
497 if (size == 0) |
497 return null; |
498 return null; |
498 // copy errors from the list to an string array |
499 // copy errors from the list to an string array |
499 String[] errors = new String[size]; |
500 String[] errors = new String[size]; |
500 for (int i = 0; i < size; i++) { |
501 for (int i = 0; i < size; i++) { |
501 errors[i] = (String) fErrors.elementAt(contextPos + i); |
502 errors[i] = fErrors.get(contextPos + i); |
502 } |
503 } |
503 // don't resize the vector: leave the errors for this attribute |
504 // don't resize the vector: leave the errors for this attribute |
504 // to the containing element |
505 // to the containing element |
505 return errors; |
506 return errors; |
506 } |
507 } |
507 |
508 |
508 public void reportError(String domain, String key, Object[] arguments, short severity) |
509 public void reportError(String domain, String key, Object[] arguments, short severity) |
509 throws XNIException { |
510 throws XNIException { |
510 String message = fErrorReporter.reportError(domain, key, arguments, severity); |
511 String message = fErrorReporter.reportError(domain, key, arguments, severity); |
511 if (fAugPSVI) { |
512 if (fAugPSVI) { |
512 fErrors.addElement(key); |
513 fErrors.add(key); |
513 fErrors.addElement(message); |
514 fErrors.add(message); |
514 } |
515 } |
515 } // reportError(String,String,Object[],short) |
516 } // reportError(String,String,Object[],short) |
516 |
517 |
517 public void reportError( |
518 public void reportError( |
518 XMLLocator location, |
519 XMLLocator location, |
521 Object[] arguments, |
522 Object[] arguments, |
522 short severity) |
523 short severity) |
523 throws XNIException { |
524 throws XNIException { |
524 String message = fErrorReporter.reportError(location, domain, key, arguments, severity); |
525 String message = fErrorReporter.reportError(location, domain, key, arguments, severity); |
525 if (fAugPSVI) { |
526 if (fAugPSVI) { |
526 fErrors.addElement(key); |
527 fErrors.add(key); |
527 fErrors.addElement(message); |
528 fErrors.add(message); |
528 } |
529 } |
529 } // reportError(XMLLocator,String,String,Object[],short) |
530 } // reportError(XMLLocator,String,String,Object[],short) |
530 } |
531 } |
531 |
532 |
532 /** Error reporter. */ |
533 /** Error reporter. */ |
1933 decl = fCurrentCM.oneTransition(element, fCurrCMState, fSubGroupHandler); |
1934 decl = fCurrentCM.oneTransition(element, fCurrCMState, fSubGroupHandler); |
1934 // it could be an element decl or a wildcard decl |
1935 // it could be an element decl or a wildcard decl |
1935 if (fCurrCMState[0] == XSCMValidator.FIRST_ERROR) { |
1936 if (fCurrCMState[0] == XSCMValidator.FIRST_ERROR) { |
1936 XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType; |
1937 XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType; |
1937 //REVISIT: is it the only case we will have particle = null? |
1938 //REVISIT: is it the only case we will have particle = null? |
1938 ArrayList next; |
1939 List<Object> next; |
1939 if (ctype.fParticle != null |
1940 if (ctype.fParticle != null |
1940 && (next = fCurrentCM.whatCanGoHere(fCurrCMState)).size() > 0) { |
1941 && (next = fCurrentCM.whatCanGoHere(fCurrCMState)).size() > 0) { |
1941 String expected = expectedStr(next); |
1942 String expected = expectedStr(next); |
1942 final int[] occurenceInfo = fCurrentCM.occurenceInfo(fCurrCMState); |
1943 final int[] occurenceInfo = fCurrentCM.occurenceInfo(fCurrCMState); |
1943 String elemExpandedQname = (element.uri != null) ? "{"+'"'+element.uri+'"'+":"+element.localpart+"}" : element.localpart; |
1944 String elemExpandedQname = (element.uri != null) ? "{"+'"'+element.uri+'"'+":"+element.localpart+"}" : element.localpart; |
2445 |
2446 |
2446 SchemaGrammar[] grammars = null; |
2447 SchemaGrammar[] grammars = null; |
2447 // have we reached the end tag of the validation root? |
2448 // have we reached the end tag of the validation root? |
2448 if (fElementDepth == 0) { |
2449 if (fElementDepth == 0) { |
2449 // 7 If the element information item is the validation root, it must be valid per Validation Root Valid (ID/IDREF) (3.3.4). |
2450 // 7 If the element information item is the validation root, it must be valid per Validation Root Valid (ID/IDREF) (3.3.4). |
2450 Iterator invIdRefs = fValidationState.checkIDRefID(); |
2451 Iterator<String> invIdRefs = fValidationState.checkIDRefID(); |
2451 fValidationState.resetIDTables(); |
2452 fValidationState.resetIDTables(); |
2452 if (invIdRefs != null) { |
2453 if (invIdRefs != null) { |
2453 while (invIdRefs.hasNext()) { |
2454 while (invIdRefs.hasNext()) { |
2454 reportSchemaError("cvc-id.1", new Object[] { invIdRefs.next() }); |
2455 reportSchemaError("cvc-id.1", new Object[] { invIdRefs.next() }); |
2455 } |
2456 } |
3507 } else { |
3508 } else { |
3508 // Constant space algorithm for a{n,m} for n > 1 and m <= unbounded |
3509 // Constant space algorithm for a{n,m} for n > 1 and m <= unbounded |
3509 // After the DFA has completed, check minOccurs and maxOccurs |
3510 // After the DFA has completed, check minOccurs and maxOccurs |
3510 // for all elements and wildcards in this content model where |
3511 // for all elements and wildcards in this content model where |
3511 // a{n,m} is subsumed to a* or a+ |
3512 // a{n,m} is subsumed to a* or a+ |
3512 ArrayList errors = fCurrentCM.checkMinMaxBounds(); |
3513 List<String> errors = fCurrentCM.checkMinMaxBounds(); |
3513 if (errors != null) { |
3514 if (errors != null) { |
3514 for (int i = 0; i < errors.size(); i += 2) { |
3515 for (int i = 0; i < errors.size(); i += 2) { |
3515 reportSchemaError( |
3516 reportSchemaError(errors.get(i), |
3516 (String) errors.get(i), |
|
3517 new Object[] { element.rawname, errors.get(i + 1) }); |
3517 new Object[] { element.rawname, errors.get(i + 1) }); |
3518 } |
3518 } |
3519 } |
3519 } |
3520 } |
3520 } |
3521 } |
3521 } |
3589 key, |
3589 key, |
3590 arguments, |
3590 arguments, |
3591 XMLErrorReporter.SEVERITY_ERROR); |
3591 XMLErrorReporter.SEVERITY_ERROR); |
3592 } |
3592 } |
3593 |
3593 |
3594 private String expectedStr(ArrayList expected) { |
3594 private String expectedStr(List<Object> expected) { |
3595 StringBuilder ret = new StringBuilder("{"); |
3595 StringBuilder ret = new StringBuilder("{"); |
3596 int size = expected.size(); |
3596 int size = expected.size(); |
3597 for (int i = 0; i < size; i++) { |
3597 for (int i = 0; i < size; i++) { |
3598 if (i > 0) |
3598 if (i > 0) |
3599 ret.append(", "); |
3599 ret.append(", "); |
3718 |
3718 |
3719 /** Current data value count. */ |
3719 /** Current data value count. */ |
3720 protected int fValuesCount; |
3720 protected int fValuesCount; |
3721 |
3721 |
3722 /** global data */ |
3722 /** global data */ |
3723 public final Vector fValues = new Vector(); |
3723 public final Vector<Object> fValues = new Vector<>(); |
3724 public ShortVector fValueTypes = null; |
3724 public ShortVector fValueTypes = null; |
3725 public Vector fItemValueTypes = null; |
3725 public Vector<ShortList> fItemValueTypes = null; |
3726 |
3726 |
3727 private boolean fUseValueTypeVector = false; |
3727 private boolean fUseValueTypeVector = false; |
3728 private int fValueTypesLength = 0; |
3728 private int fValueTypesLength = 0; |
3729 private short fValueType = 0; |
3729 private short fValueType = 0; |
3730 |
3730 |
3776 } // end clear():void |
3776 } // end clear():void |
3777 |
3777 |
3778 // appends the contents of one ValueStore to those of us. |
3778 // appends the contents of one ValueStore to those of us. |
3779 public void append(ValueStoreBase newVal) { |
3779 public void append(ValueStoreBase newVal) { |
3780 for (int i = 0; i < newVal.fValues.size(); i++) { |
3780 for (int i = 0; i < newVal.fValues.size(); i++) { |
3781 fValues.addElement(newVal.fValues.elementAt(i)); |
3781 fValues.add(newVal.fValues.get(i)); |
3782 } |
3782 } |
3783 } // append(ValueStoreBase) |
3783 } // append(ValueStoreBase) |
3784 |
3784 |
3785 /** Start scope for value store. */ |
3785 /** Start scope for value store. */ |
3786 public void startValueScope() { |
3786 public void startValueScope() { |
3891 fLocalItemValueTypes[i] = itemValueType; |
3891 fLocalItemValueTypes[i] = itemValueType; |
3892 if (fValuesCount == fFieldCount) { |
3892 if (fValuesCount == fFieldCount) { |
3893 checkDuplicateValues(); |
3893 checkDuplicateValues(); |
3894 // store values |
3894 // store values |
3895 for (i = 0; i < fFieldCount; i++) { |
3895 for (i = 0; i < fFieldCount; i++) { |
3896 fValues.addElement(fLocalValues[i]); |
3896 fValues.add(fLocalValues[i]); |
3897 addValueType(fLocalValueTypes[i]); |
3897 addValueType(fLocalValueTypes[i]); |
3898 addItemValueType(fLocalItemValueTypes[i]); |
3898 addItemValueType(fLocalItemValueTypes[i]); |
3899 } |
3899 } |
3900 } |
3900 } |
3901 } // addValue(String,Field) |
3901 } // addValue(String,Field) |
3910 final int size = fValues.size(); |
3910 final int size = fValues.size(); |
3911 LOOP : for (int i = 0; i < size; i = next) { |
3911 LOOP : for (int i = 0; i < size; i = next) { |
3912 next = i + fFieldCount; |
3912 next = i + fFieldCount; |
3913 for (int j = 0; j < fFieldCount; j++) { |
3913 for (int j = 0; j < fFieldCount; j++) { |
3914 Object value1 = fLocalValues[j]; |
3914 Object value1 = fLocalValues[j]; |
3915 Object value2 = fValues.elementAt(i); |
3915 Object value2 = fValues.get(i); |
3916 short valueType1 = fLocalValueTypes[j]; |
3916 short valueType1 = fLocalValueTypes[j]; |
3917 short valueType2 = getValueTypeAt(i); |
3917 short valueType2 = getValueTypeAt(i); |
3918 if (value1 == null || value2 == null || valueType1 != valueType2 || !(value1.equals(value2))) { |
3918 if (value1 == null || value2 == null || valueType1 != valueType2 || !(value1.equals(value2))) { |
3919 continue LOOP; |
3919 continue LOOP; |
3920 } |
3920 } |
3938 * values, otherwise the index of the first field in the |
3938 * values, otherwise the index of the first field in the |
3939 * key sequence. |
3939 * key sequence. |
3940 */ |
3940 */ |
3941 public int contains(ValueStoreBase vsb) { |
3941 public int contains(ValueStoreBase vsb) { |
3942 |
3942 |
3943 final Vector values = vsb.fValues; |
3943 final Vector<Object> values = vsb.fValues; |
3944 final int size1 = values.size(); |
3944 final int size1 = values.size(); |
3945 if (fFieldCount <= 1) { |
3945 if (fFieldCount <= 1) { |
3946 for (int i = 0; i < size1; ++i) { |
3946 for (int i = 0; i < size1; ++i) { |
3947 short val = vsb.getValueTypeAt(i); |
3947 short val = vsb.getValueTypeAt(i); |
3948 if (!valueTypeContains(val) || !fValues.contains(values.elementAt(i))) { |
3948 if (!valueTypeContains(val) || !fValues.contains(values.get(i))) { |
3949 return i; |
3949 return i; |
3950 } |
3950 } |
3951 else if(val == XSConstants.LIST_DT || val == XSConstants.LISTOFUNION_DT) { |
3951 else if(val == XSConstants.LIST_DT || val == XSConstants.LISTOFUNION_DT) { |
3952 ShortList list1 = vsb.getItemValueTypeAt(i); |
3952 ShortList list1 = vsb.getItemValueTypeAt(i); |
3953 if (!itemValueTypeContains(list1)) { |
3953 if (!itemValueTypeContains(list1)) { |
3962 /** Iterate over each set of fields. **/ |
3962 /** Iterate over each set of fields. **/ |
3963 OUTER: for (int i = 0; i < size1; i += fFieldCount) { |
3963 OUTER: for (int i = 0; i < size1; i += fFieldCount) { |
3964 /** Check whether this set is contained in the value store. **/ |
3964 /** Check whether this set is contained in the value store. **/ |
3965 INNER: for (int j = 0; j < size2; j += fFieldCount) { |
3965 INNER: for (int j = 0; j < size2; j += fFieldCount) { |
3966 for (int k = 0; k < fFieldCount; ++k) { |
3966 for (int k = 0; k < fFieldCount; ++k) { |
3967 final Object value1 = values.elementAt(i+k); |
3967 final Object value1 = values.get(i+k); |
3968 final Object value2 = fValues.elementAt(j+k); |
3968 final Object value2 = fValues.get(j+k); |
3969 final short valueType1 = vsb.getValueTypeAt(i+k); |
3969 final short valueType1 = vsb.getValueTypeAt(i+k); |
3970 final short valueType2 = getValueTypeAt(j+k); |
3970 final short valueType2 = getValueTypeAt(j+k); |
3971 if (value1 != value2 && (valueType1 != valueType2 || value1 == null || !value1.equals(value2))) { |
3971 if (value1 != value2 && (valueType1 != valueType2 || value1 == null || !value1.equals(value2))) { |
3972 continue INNER; |
3972 continue INNER; |
3973 } |
3973 } |
4017 return fTempBuffer.toString(); |
4017 return fTempBuffer.toString(); |
4018 |
4018 |
4019 } // toString(Object[]):String |
4019 } // toString(Object[]):String |
4020 |
4020 |
4021 /** Returns a string of the specified values. */ |
4021 /** Returns a string of the specified values. */ |
4022 protected String toString(Vector values, int start, int length) { |
4022 protected String toString(Vector<Object> values, int start, int length) { |
4023 |
4023 |
4024 // no values |
4024 // no values |
4025 if (length == 0) { |
4025 if (length == 0) { |
4026 return ""; |
4026 return ""; |
4027 } |
4027 } |
4028 |
4028 |
4029 // one value |
4029 // one value |
4030 if (length == 1) { |
4030 if (length == 1) { |
4031 return String.valueOf(values.elementAt(start)); |
4031 return String.valueOf(values.get(start)); |
4032 } |
4032 } |
4033 |
4033 |
4034 // construct value string |
4034 // construct value string |
4035 StringBuilder str = new StringBuilder(); |
4035 StringBuilder str = new StringBuilder(); |
4036 for (int i = 0; i < length; i++) { |
4036 for (int i = 0; i < length; i++) { |
4037 if (i > 0) { |
4037 if (i > 0) { |
4038 str.append(','); |
4038 str.append(','); |
4039 } |
4039 } |
4040 str.append(values.elementAt(start + i)); |
4040 str.append(values.get(start + i)); |
4041 } |
4041 } |
4042 return str.toString(); |
4042 return str.toString(); |
4043 |
4043 |
4044 } // toString(Vector,int,int):String |
4044 } // toString(Vector,int,int):String |
4045 |
4045 |
4107 } |
4107 } |
4108 else if (!(fItemValueType == itemValueType || |
4108 else if (!(fItemValueType == itemValueType || |
4109 (fItemValueType != null && fItemValueType.equals(itemValueType)))) { |
4109 (fItemValueType != null && fItemValueType.equals(itemValueType)))) { |
4110 fUseItemValueTypeVector = true; |
4110 fUseItemValueTypeVector = true; |
4111 if (fItemValueTypes == null) { |
4111 if (fItemValueTypes == null) { |
4112 fItemValueTypes = new Vector(fItemValueTypesLength * 2); |
4112 fItemValueTypes = new Vector<>(fItemValueTypesLength * 2); |
4113 } |
4113 } |
4114 for (int i = 1; i < fItemValueTypesLength; ++i) { |
4114 for (int i = 1; i < fItemValueTypesLength; ++i) { |
4115 fItemValueTypes.add(fItemValueType); |
4115 fItemValueTypes.add(fItemValueType); |
4116 } |
4116 } |
4117 fItemValueTypes.add(itemValueType); |
4117 fItemValueTypes.add(itemValueType); |
4118 } |
4118 } |
4119 } |
4119 } |
4120 |
4120 |
4121 private ShortList getItemValueTypeAt(int index) { |
4121 private ShortList getItemValueTypeAt(int index) { |
4122 if (fUseItemValueTypeVector) { |
4122 if (fUseItemValueTypeVector) { |
4123 return (ShortList) fItemValueTypes.elementAt(index); |
4123 return (ShortList) fItemValueTypes.get(index); |
4124 } |
4124 } |
4125 return fItemValueType; |
4125 return fItemValueType; |
4126 } |
4126 } |
4127 |
4127 |
4128 private boolean itemValueTypeContains(ShortList value) { |
4128 private boolean itemValueTypeContains(ShortList value) { |
4290 // |
4290 // |
4291 final LocalIDKey fLocalId = new LocalIDKey(); |
4291 final LocalIDKey fLocalId = new LocalIDKey(); |
4292 // values stores |
4292 // values stores |
4293 |
4293 |
4294 /** stores all global Values stores. */ |
4294 /** stores all global Values stores. */ |
4295 protected final ArrayList fValueStores = new ArrayList(); |
4295 protected final List<ValueStoreBase> fValueStores = new ArrayList<>(); |
4296 |
4296 |
4297 /** |
4297 /** |
4298 * Values stores associated to specific identity constraints. |
4298 * Values stores associated to specific identity constraints. |
4299 * This map maps IdentityConstraints and |
4299 * This map maps IdentityConstraints and |
4300 * the 0-based element on which their selectors first matched to |
4300 * the 0-based element on which their selectors first matched to |
4350 fGlobalMapStack.removeAllElements(); |
4350 fGlobalMapStack.removeAllElements(); |
4351 } // startDocument() |
4351 } // startDocument() |
4352 |
4352 |
4353 // startElement: pushes the current fGlobalIDConstraintMap |
4353 // startElement: pushes the current fGlobalIDConstraintMap |
4354 // onto fGlobalMapStack and clears fGlobalIDConstraint map. |
4354 // onto fGlobalMapStack and clears fGlobalIDConstraint map. |
|
4355 @SuppressWarnings("unchecked") |
4355 public void startElement() { |
4356 public void startElement() { |
4356 // only clone the map when there are elements |
4357 // only clone the map when there are elements |
4357 if (fGlobalIDConstraintMap.size() > 0) |
4358 if (fGlobalIDConstraintMap.size() > 0) |
4358 fGlobalMapStack.push((Map<IdentityConstraint, ValueStoreBase>) |
4359 fGlobalMapStack.push((Map<IdentityConstraint, ValueStoreBase>) |
4359 ((HashMap)fGlobalIDConstraintMap).clone()); |
4360 ((HashMap<IdentityConstraint, ValueStoreBase>)fGlobalIDConstraintMap).clone()); |
4360 else |
4361 else |
4361 fGlobalMapStack.push(null); |
4362 fGlobalMapStack.push(null); |
4362 fGlobalIDConstraintMap.clear(); |
4363 fGlobalIDConstraintMap.clear(); |
4363 } // startElement(void) |
4364 } // startElement(void) |
4364 |
4365 |