blob: 0ab8d52331bfe81153293abe79e2f74d75596a9d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.bval.xml;
import org.apache.bval.MetaBeanManager;
import org.apache.bval.model.MetaBean;
import org.apache.bval.model.MetaProperty;
import org.apache.bval.util.PrivilegedActions;
import java.util.Map;
import static org.apache.bval.model.Features.Property.REF_BEAN_ID;
/**
* Description: internal implementation class to construct metabeans with
* factories and from xstream xml files. You can register different
* XMLMetaBeanLoaders (see addLoader()) to register xstream-xml-files that
* contain meta-data. You can merge + unify meta data with method
* enrichCopies(). <br/>
* User: roman.stumm<br>
* Date: 17.06.2010<br>
* Time: 09:47:14<br>
*/
public class XMLMetaBeanManager extends MetaBeanManager implements XMLMetaBeanRegistry, MetaBeanEnricher {
public XMLMetaBeanManager() {
this(new XMLMetaBeanBuilder());
}
public XMLMetaBeanManager(XMLMetaBeanBuilder builder) {
super(builder);
}
public void addResourceLoader(String resource) {
addLoader(new XMLMetaBeanURLLoader(PrivilegedActions.getClassLoader(getClass()).getResource(resource)));
}
public synchronized void addLoader(XMLMetaBeanLoader loader) {
((XMLMetaBeanBuilder) builder).addLoader(loader);
cache.clear(); // clear because new loaders can affect ALL MetaBeans
// already created!
complete = false;
}
/**
* @param infos
* - the patches to apply
* @return all MetaBeans for classes that have a xml descriptor and
* additional the MetaBeans loaded by the given loaders. The given
* loaders may also return patches for MetaBeans that have also been
* returned by other loaders. The beans with patches for references
* to patched beans will be copied.
*/
public Map<String, MetaBean> enrichCopies(XMLMetaBeanInfos... infos) {
Map<String, MetaBean> cached = findAll();
try {
Map<String, MetaBean> patched = ((XMLMetaBeanBuilder) builder).enrichCopies(cached, infos);
for (Object entry : patched.values()) {
MetaBean meta = (MetaBean) entry;
computeRelationships(meta, patched);
}
return patched;
} catch (RuntimeException e) {
throw e; // do not wrap runtime exceptions
} catch (Exception e) {
throw new IllegalArgumentException("error enriching beanInfos", e);
}
}
/**
*
* @return all MetaBeans for classes that have a xml descriptor: key =
* bean.id, value = MetaBean
*/
public Map<String, MetaBean> findAll() {
if (!complete) {
try {
Map<String, MetaBean> allBuilt = builder.buildAll();
for (MetaBean meta : allBuilt.values()) {
MetaBean cached = cache.findForId(meta.getId());
if (cached == null) {
cache.cache(meta);
}
}
Map<String, MetaBean> map = cache.findAll();
for (Object oentry : map.values()) {
MetaBean meta = (MetaBean) oentry;
computeRelationships(meta, map);
}
complete = true;
return map;
} catch (RuntimeException e) {
throw e; // do not wrap runtime exceptions
} catch (Exception e) {
throw new IllegalArgumentException("error creating beanInfos", e);
}
} else {
return cache.findAll();
}
}
protected void computeRelationships(MetaBean beanInfo, Map<String, MetaBean> cached) {
for (MetaProperty prop : beanInfo.getProperties()) {
String beanRef = (String) prop.getFeature(REF_BEAN_ID);
if (beanRef != null) {
prop.setMetaBean(cached.get(beanRef));
}
}
}
protected void computeRelatedMetaBean(MetaProperty prop, String beanRef) {
if (beanRef != null) {
prop.setMetaBean(findForId(beanRef));
} else {
super.computeRelatedMetaBean(prop, beanRef);
}
}
}