| /* |
| * 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); |
| } |
| } |
| } |