| /* Copyright 2004 The Apache Software Foundation |
| * |
| * Licensed under the Apache 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.apache.org/licenses/LICENSE-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.apache.xmlbeans.impl.schema; |
| |
| import org.apache.xmlbeans.*; |
| import org.apache.xmlbeans.impl.common.NameUtil; |
| |
| import javax.xml.namespace.QName; |
| import java.util.LinkedHashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import static org.apache.xmlbeans.impl.schema.SchemaTypeSystemImpl.*; |
| |
| class SchemaTypePool { |
| private final SchemaTypeSystemImpl typeSystem; |
| private final Map<String, SchemaComponent.Ref> _handlesToRefs = new LinkedHashMap<>(); |
| // populated on write |
| private final Map<SchemaComponent, String> _componentsToHandles = new LinkedHashMap<>(); |
| private boolean _started; |
| |
| |
| /** |
| * Constructs an empty HandlePool to be populated. |
| */ |
| SchemaTypePool(SchemaTypeSystemImpl typeSystem) { |
| this.typeSystem = typeSystem; |
| } |
| |
| private String addUniqueHandle(SchemaComponent obj, String base) { |
| // we lowercase handles because of case-insensitive Windows filenames!!! |
| base = base.toLowerCase(Locale.ROOT); |
| String handle = base; |
| for (int index = 2; _handlesToRefs.containsKey(handle); index++) { |
| handle = base + index; |
| } |
| _handlesToRefs.put(handle, obj.getComponentRef()); |
| _componentsToHandles.put(obj, handle); |
| return handle; |
| } |
| |
| String handleForComponent(SchemaComponent comp) { |
| if (comp == null) { |
| return null; |
| } |
| if (comp.getTypeSystem() != typeSystem) { |
| throw new IllegalArgumentException("Cannot supply handles for types from another type system"); |
| } |
| if (comp instanceof SchemaType) { |
| return handleForType((SchemaType) comp); |
| } |
| if (comp instanceof SchemaGlobalElement) { |
| return handleForElement((SchemaGlobalElement) comp); |
| } |
| if (comp instanceof SchemaGlobalAttribute) { |
| return handleForAttribute((SchemaGlobalAttribute) comp); |
| } |
| if (comp instanceof SchemaModelGroup) { |
| return handleForModelGroup((SchemaModelGroup) comp); |
| } |
| if (comp instanceof SchemaAttributeGroup) { |
| return handleForAttributeGroup((SchemaAttributeGroup) comp); |
| } |
| if (comp instanceof SchemaIdentityConstraint) { |
| return handleForIdentityConstraint((SchemaIdentityConstraint) comp); |
| } |
| throw new IllegalStateException("Component type cannot have a handle"); |
| } |
| |
| String handleForElement(SchemaGlobalElement element) { |
| if (element == null) { |
| return null; |
| } |
| if (element.getTypeSystem() != typeSystem) { |
| throw new IllegalArgumentException("Cannot supply handles for types from another type system"); |
| } |
| String handle = _componentsToHandles.get(element); |
| if (handle == null) { |
| handle = addUniqueHandle(element, NameUtil.upperCamelCase(element.getName().getLocalPart()) + "Element"); |
| } |
| return handle; |
| } |
| |
| String handleForAttribute(SchemaGlobalAttribute attribute) { |
| if (attribute == null) { |
| return null; |
| } |
| if (attribute.getTypeSystem() != typeSystem) { |
| throw new IllegalArgumentException("Cannot supply handles for types from another type system"); |
| } |
| String handle = _componentsToHandles.get(attribute); |
| if (handle == null) { |
| handle = addUniqueHandle(attribute, NameUtil.upperCamelCase(attribute.getName().getLocalPart()) + "Attribute"); |
| } |
| return handle; |
| } |
| |
| String handleForModelGroup(SchemaModelGroup group) { |
| if (group == null) { |
| return null; |
| } |
| if (group.getTypeSystem() != typeSystem) { |
| throw new IllegalArgumentException("Cannot supply handles for types from another type system"); |
| } |
| String handle = _componentsToHandles.get(group); |
| if (handle == null) { |
| handle = addUniqueHandle(group, NameUtil.upperCamelCase(group.getName().getLocalPart()) + "ModelGroup"); |
| } |
| return handle; |
| } |
| |
| String handleForAttributeGroup(SchemaAttributeGroup group) { |
| if (group == null) { |
| return null; |
| } |
| if (group.getTypeSystem() != typeSystem) { |
| throw new IllegalArgumentException("Cannot supply handles for types from another type system"); |
| } |
| String handle = _componentsToHandles.get(group); |
| if (handle == null) { |
| handle = addUniqueHandle(group, NameUtil.upperCamelCase(group.getName().getLocalPart()) + "AttributeGroup"); |
| } |
| return handle; |
| } |
| |
| String handleForIdentityConstraint(SchemaIdentityConstraint idc) { |
| if (idc == null) { |
| return null; |
| } |
| if (idc.getTypeSystem() != typeSystem) { |
| throw new IllegalArgumentException("Cannot supply handles for types from another type system"); |
| } |
| String handle = _componentsToHandles.get(idc); |
| if (handle == null) { |
| handle = addUniqueHandle(idc, NameUtil.upperCamelCase(idc.getName().getLocalPart()) + "IdentityConstraint"); |
| } |
| return handle; |
| } |
| |
| String handleForType(SchemaType type) { |
| if (type == null) { |
| return null; |
| } |
| if (type.getTypeSystem() != typeSystem) { |
| throw new IllegalArgumentException("Cannot supply handles for types from another type system"); |
| } |
| String handle = _componentsToHandles.get(type); |
| if (handle == null) { |
| QName name = type.getName(); |
| String suffix = ""; |
| if (name == null) { |
| if (type.isDocumentType()) { |
| name = type.getDocumentElementName(); |
| suffix = "Doc"; |
| } else if (type.isAttributeType()) { |
| name = type.getAttributeTypeAttributeName(); |
| suffix = "AttrType"; |
| } else if (type.getContainerField() != null) { |
| name = type.getContainerField().getName(); |
| suffix = type.getContainerField().isAttribute() ? "Attr" : "Elem"; |
| } |
| } |
| |
| String baseName; |
| String uniq = Integer.toHexString(type.toString().hashCode() | 0x80000000).substring(4).toUpperCase(Locale.ROOT); |
| if (name == null) { |
| baseName = "Anon" + uniq + "Type"; |
| } else { |
| baseName = NameUtil.upperCamelCase(name.getLocalPart()) + uniq + suffix + "Type"; |
| } |
| |
| handle = addUniqueHandle(type, baseName); |
| } |
| |
| return handle; |
| } |
| |
| SchemaComponent.Ref refForHandle(String handle) { |
| if (handle == null) { |
| return null; |
| } |
| |
| return _handlesToRefs.get(handle); |
| } |
| |
| void startWriteMode() { |
| _started = true; |
| _componentsToHandles.clear(); |
| for (String handle : _handlesToRefs.keySet()) { |
| SchemaComponent comp = _handlesToRefs.get(handle).getComponent(); |
| _componentsToHandles.put(comp, handle); |
| } |
| } |
| |
| void writeHandlePool(XsbReader reader) { |
| reader.writeShort(_componentsToHandles.size()); |
| _componentsToHandles.forEach((comp, handle) -> { |
| reader.writeString(handle); |
| reader.writeShort(fileTypeFromComponentType(comp.getComponentType())); |
| }); |
| } |
| |
| int fileTypeFromComponentType(int componentType) { |
| switch (componentType) { |
| case SchemaComponent.TYPE: |
| return SchemaTypeSystemImpl.FILETYPE_SCHEMATYPE; |
| case SchemaComponent.ELEMENT: |
| return SchemaTypeSystemImpl.FILETYPE_SCHEMAELEMENT; |
| case SchemaComponent.ATTRIBUTE: |
| return SchemaTypeSystemImpl.FILETYPE_SCHEMAATTRIBUTE; |
| case SchemaComponent.MODEL_GROUP: |
| return SchemaTypeSystemImpl.FILETYPE_SCHEMAMODELGROUP; |
| case SchemaComponent.ATTRIBUTE_GROUP: |
| return SchemaTypeSystemImpl.FILETYPE_SCHEMAATTRIBUTEGROUP; |
| case SchemaComponent.IDENTITY_CONSTRAINT: |
| return SchemaTypeSystemImpl.FILETYPE_SCHEMAIDENTITYCONSTRAINT; |
| default: |
| throw new IllegalStateException("Unexpected component type"); |
| } |
| } |
| |
| void readHandlePool(XsbReader reader) { |
| if (_handlesToRefs.size() != 0 || _started) { |
| throw new IllegalStateException("Nonempty handle set before read"); |
| } |
| |
| int size = reader.readShort(); |
| for (int i = 0; i < size; i++) { |
| String handle = reader.readString(); |
| int code = reader.readShort(); |
| SchemaComponent.Ref result; |
| switch (code) { |
| case FILETYPE_SCHEMATYPE: |
| result = new SchemaType.Ref(typeSystem, handle); |
| break; |
| case FILETYPE_SCHEMAELEMENT: |
| result = new SchemaGlobalElement.Ref(typeSystem, handle); |
| break; |
| case FILETYPE_SCHEMAATTRIBUTE: |
| result = new SchemaGlobalAttribute.Ref(typeSystem, handle); |
| break; |
| case FILETYPE_SCHEMAMODELGROUP: |
| result = new SchemaModelGroup.Ref(typeSystem, handle); |
| break; |
| case FILETYPE_SCHEMAATTRIBUTEGROUP: |
| result = new SchemaAttributeGroup.Ref(typeSystem, handle); |
| break; |
| case FILETYPE_SCHEMAIDENTITYCONSTRAINT: |
| result = new SchemaIdentityConstraint.Ref(typeSystem, handle); |
| break; |
| default: |
| throw new SchemaTypeLoaderException("Schema index has an unrecognized entry of type " + code, typeSystem.getName(), handle, SchemaTypeLoaderException.UNRECOGNIZED_INDEX_ENTRY); |
| } |
| _handlesToRefs.put(handle, result); |
| } |
| } |
| } |
| |