blob: a221fe0c58bc2ee5b012b61470c61d35bfb9fc5e [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.marshal;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.impl.binding.bts.BindingLoader;
import org.apache.xmlbeans.impl.binding.bts.BindingType;
import org.apache.xmlbeans.impl.binding.bts.BindingTypeVisitor;
import org.apache.xmlbeans.impl.binding.bts.BuiltinBindingType;
import org.apache.xmlbeans.impl.binding.bts.ByNameBean;
import org.apache.xmlbeans.impl.binding.bts.ListArrayType;
import org.apache.xmlbeans.impl.binding.bts.SimpleBindingType;
import org.apache.xmlbeans.impl.binding.bts.SimpleContentBean;
import org.apache.xmlbeans.impl.binding.bts.SimpleDocumentBinding;
import org.apache.xmlbeans.impl.binding.bts.WrappedArrayType;
import org.apache.xmlbeans.impl.binding.bts.JaxrpcEnumType;
import org.apache.xmlbeans.impl.common.ConcurrentReaderHashMap;
import java.util.HashMap;
import java.util.Map;
/**
* caching factory for runtime binding types
*/
final class RuntimeTypeFactory
{
//concurrent hashMap allows us to do hash lookups outside of any sync blocks,
//and successful lookups involve no locking, which should be
//99% of the cases in any sort of long running process
private final Map initedTypeMap = new ConcurrentReaderHashMap();
private final Map tempTypeMap = new HashMap();
//access to this object must be inside a synchronized block.
private final TypeVisitor typeVisitor = new TypeVisitor();
RuntimeTypeFactory()
{
}
public RuntimeBindingType createRuntimeType(BindingType type,
RuntimeBindingTypeTable type_table,
BindingLoader binding_loader)
throws XmlException
{
assert type != null;
RuntimeBindingType rtype = (RuntimeBindingType)initedTypeMap.get(type);
if (rtype != null) return rtype;
//safe but slow creation of new type.
synchronized (this) {
rtype = (RuntimeBindingType)tempTypeMap.get(type);
if (rtype == null) {
rtype = allocateType(type);
tempTypeMap.put(type, rtype);
rtype.initialize(type_table, binding_loader, this);
initedTypeMap.put(type, rtype);
tempTypeMap.remove(type); // save some memory.
}
}
assert rtype != null;
return rtype;
}
//overloaded, more strongly typed versions of createRuntimeType.
//the idea being that this class maintains the matching of the
//two type hiearchies and all casting is done here.
public WrappedArrayRuntimeBindingType createRuntimeType(WrappedArrayType type,
RuntimeBindingTypeTable type_table,
BindingLoader binding_loader)
throws XmlException
{
final RuntimeBindingType rtt =
createRuntimeTypeInternal(type, type_table, binding_loader);
return (WrappedArrayRuntimeBindingType)rtt;
}
public ListArrayRuntimeBindingType createRuntimeType(ListArrayType type,
RuntimeBindingTypeTable type_table,
BindingLoader binding_loader)
throws XmlException
{
final RuntimeBindingType rtt =
createRuntimeTypeInternal(type, type_table, binding_loader);
return (ListArrayRuntimeBindingType)rtt;
}
public BuiltinRuntimeBindingType createRuntimeType(BuiltinBindingType type,
RuntimeBindingTypeTable type_table,
BindingLoader binding_loader)
throws XmlException
{
final RuntimeBindingType rtt =
createRuntimeTypeInternal(type, type_table, binding_loader);
return (BuiltinRuntimeBindingType)rtt;
}
public SimpleRuntimeBindingType createRuntimeType(SimpleBindingType type,
RuntimeBindingTypeTable type_table,
BindingLoader binding_loader)
throws XmlException
{
final RuntimeBindingType rtt =
createRuntimeTypeInternal(type, type_table, binding_loader);
return (SimpleRuntimeBindingType)rtt;
}
public ByNameRuntimeBindingType createRuntimeType(ByNameBean type,
RuntimeBindingTypeTable type_table,
BindingLoader binding_loader)
throws XmlException
{
final RuntimeBindingType rtt =
createRuntimeTypeInternal(type, type_table, binding_loader);
return (ByNameRuntimeBindingType)rtt;
}
public SimpleContentRuntimeBindingType createRuntimeType(SimpleContentBean type,
RuntimeBindingTypeTable type_table,
BindingLoader binding_loader)
throws XmlException
{
final RuntimeBindingType rtt =
createRuntimeTypeInternal(type, type_table, binding_loader);
return (SimpleContentRuntimeBindingType)rtt;
}
public JaxrpcEnumRuntimeBindingType createRuntimeType(JaxrpcEnumType type,
RuntimeBindingTypeTable type_table,
BindingLoader binding_loader)
throws XmlException
{
final RuntimeBindingType rtt =
createRuntimeTypeInternal(type, type_table, binding_loader);
return (JaxrpcEnumRuntimeBindingType)rtt;
}
//avoids a cast to deal with overloaded methods
private RuntimeBindingType createRuntimeTypeInternal(BindingType type,
RuntimeBindingTypeTable type_table,
BindingLoader binding_loader)
throws XmlException
{
return createRuntimeType(type, type_table, binding_loader);
}
private RuntimeBindingType allocateType(BindingType type)
throws XmlException
{
type.accept(typeVisitor);
return typeVisitor.getRuntimeBindingType();
}
private static final class TypeVisitor
implements BindingTypeVisitor
{
private RuntimeBindingType runtimeBindingType;
public RuntimeBindingType getRuntimeBindingType()
{
return runtimeBindingType;
}
public void visit(BuiltinBindingType builtinBindingType)
throws XmlException
{
runtimeBindingType = new BuiltinRuntimeBindingType(builtinBindingType);
}
public void visit(ByNameBean byNameBean)
throws XmlException
{
runtimeBindingType = new ByNameRuntimeBindingType(byNameBean);
}
public void visit(SimpleContentBean simpleContentBean)
throws XmlException
{
runtimeBindingType = new SimpleContentRuntimeBindingType(simpleContentBean);
}
public void visit(SimpleBindingType simpleBindingType)
throws XmlException
{
runtimeBindingType = new SimpleRuntimeBindingType(simpleBindingType);
}
public void visit(JaxrpcEnumType jaxrpcEnumType)
throws XmlException
{
runtimeBindingType = new JaxrpcEnumRuntimeBindingType(jaxrpcEnumType);
}
public void visit(SimpleDocumentBinding simpleDocumentBinding)
throws XmlException
{
throw new AssertionError("not valid here: " + simpleDocumentBinding);
}
public void visit(WrappedArrayType wrappedArrayType)
throws XmlException
{
runtimeBindingType = new WrappedArrayRuntimeBindingType(wrappedArrayType);
}
public void visit(ListArrayType listArrayType)
throws XmlException
{
runtimeBindingType = new ListArrayRuntimeBindingType(listArrayType);
}
}
}