blob: 0f58fdbc4b9bd0fa38c4751807a2b5293dec66c3 [file] [log] [blame]
/* 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);
}
}
}