/* * Lokomo OneCMDB - An Open Source Software for Configuration * Management of Datacenter Resources * * Copyright (C) 2006 Lokomo Systems AB * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. * * Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via * paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33 * Danderyd, Sweden. * */ package org.onecmdb.core.utils.xml; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.onecmdb.core.IRFC; import org.onecmdb.core.IType; import org.onecmdb.core.internal.model.primitivetypes.SimpleTypeFactory; import org.onecmdb.core.utils.IBeanProvider; import org.onecmdb.core.utils.bean.CiBean; public class BeanScope implements IBeanScope { private IBeanProvider beanProvider; private IBeanProvider baseBeanProvider; private IBeanProvider remoteBeanProvider; private Set<String> externalReferences = new HashSet<String>(); private RfcContainer rfcContainer = new RfcContainer(); private List<CiBean> processedBeanOrder = new ArrayList<CiBean>(); private HashSet<String> processedBeans = new HashSet<String>(); private HashMap<String, CiBean> beanMap = new HashMap<String, CiBean>(); private String currentBean; private Log log = LogFactory.getLog(this.getClass()); private HashSet<String> simpleTypesUsed = new HashSet<String>(); private HashMap<String, CiBean> repositoryBeansUsed = new HashMap<String, CiBean>(); private HashMap<String, List<CiBean>> duplicatedBeans = new HashMap<String, List<CiBean>>(); private boolean validationEnabled = true; private BeanCompare compare; // {{{ Spring IOC public void setBeanProvider(IBeanProvider provider) { this.beanProvider = provider; } public IBeanProvider getBeanProvider() { return(this.beanProvider); } public void setBaseBeanProvider(IBeanProvider provider) { this.baseBeanProvider = provider; } public void setRemoteBeanProvider(IBeanProvider provider) { this.remoteBeanProvider = provider; } public void setValidation(boolean value) { this.validationEnabled = value; } // }}} END Spring IOC public void process() { // New comparer. compare = new BeanCompare(); BeanRFCGenerator gen = new BeanRFCGenerator(); gen.setScope(this); gen.setRfcContainer(rfcContainer); compare.setRfcGenerator(gen); List<CiBean> baseList = getBaseBeans(); List<CiBean> beans = beanProvider.getBeans(); // If we pass in a base list of beans then // we enforce more strict compare, with ID, // that will support modification on alias. boolean hasID = true; if (baseList.size() == 0 || beans.size() == 0) { hasID = false; } for (CiBean b : baseList) { if (b.getId() == null) { hasID = false; break; } CiBean localBean = beanProvider.getBean(b.getAlias()); if (localBean != null) { if (localBean.getId() == null) { hasID = false; break; } } } if (hasID) { setValidation(false); compare.compareID(beans, baseList); } else { // Create mapping. for (CiBean bean : beans) { if (beanMap.containsKey(bean.getAlias())) { List<CiBean> list = duplicatedBeans.get(bean.getAlias()); if (list == null) { list = new ArrayList<CiBean>(); duplicatedBeans.put(bean.getAlias(), list); } list.add(bean); list.add(beanMap.get(bean.getAlias())); } else { beanMap.put(bean.getAlias(), bean); } } for (CiBean bean : beans) { currentBean = bean.getAlias(); if (!processedBeans.contains(currentBean)) { processBean(currentBean); } } // Process base beans to handle delete. for (CiBean base : getBaseBeans()) { String beanName = base.getAlias(); CiBean bean = beanMap.get(beanName); // If bean exists we have already processed it. if (bean == null) { compare.compare(getBaseBean(beanName), getRemoteBean(beanName), bean); } } } log.info("External references <validation enabled="+ validationEnabled +">"); for (String s : externalReferences) { log.info("\t" + s); } dumpRfcs(rfcContainer.getOrderedRfcs(), 0); } public Set<String> getUnresolvedAliases() { return (externalReferences); } public List<IRFC> getRFCs() { return (rfcContainer.getOrderedRfcs()); } private void dumpRfcs(List<IRFC> rfcs, int level) { if (!log.isDebugEnabled()) { return; } String tab = ""; for (int i = 0; i < level; i++) { tab += " "; } for (IRFC rfc : rfcs) { log.debug(tab + rfc.getSummary()); dumpRfcs(rfc.getRfcs(), level + 1); } } public void referenceBean(CiBean source, String how, String beanName) { if (!validationEnabled ) { return; } CiBean bean = beanMap.get(beanName); if (bean == null) { // validate agains removeProvider... if (remoteBeanProvider != null) { CiBean remoteBean = remoteBeanProvider.getBean(beanName); if (remoteBean != null) { repositoryBeansUsed.put(beanName, remoteBean); return; } } // Check if primitive type... IType type = SimpleTypeFactory.getInstance().toType(beanName); if (type != null) { simpleTypesUsed.add(beanName); } else { log.warn("Bean '" + beanName + "' is not resolved!"); externalReferences.add(beanName); } } } public void processBean(String beanName) { log.debug("Process BEAN - " + beanName); if (processedBeans.contains(beanName)) { if (currentBean.equals(beanName)) { // Cyclic dependency give up. throw new IllegalArgumentException("Cyclic bean dependency to " + beanName); } return; } CiBean bean = beanMap.get(beanName); if (bean == null) { //referenceBean(beanName); return; } log.info("Processing " + beanName); // Add it before here to avoid cyclic loops, // will be detected by the currentBean. processedBeans.add(beanName); // Could we support 3 way compare? // Cmp base against remote. // if no changes.. --> cmp base local // if changes conflict!!!! // New worker. compare.compare(getBaseBean(beanName), getRemoteBean(beanName), bean); //worker.cmpBean(getRemoteBean(beanName), bean, this, rfcContainer); if (bean != null) { processedBeanOrder.add(bean); } } private List<CiBean> getBaseBeans() { if (baseBeanProvider == null) { return (Collections.EMPTY_LIST); } List<CiBean> baseBeans = baseBeanProvider.getBeans(); return (baseBeans); } private CiBean getBaseBean(String alias) { if (baseBeanProvider == null) { return (null); } CiBean baseBean = baseBeanProvider.getBean(alias); return (baseBean); } public CiBean getLocalBean(String alias) { return(beanMap.get(alias)); } public CiBean getRemoteBean(String alias) { if (remoteBeanProvider == null) { return (null); } CiBean remoteBean = remoteBeanProvider.getBean(alias); return (remoteBean); } public List<CiBean> getProcessedBeans() { return (processedBeanOrder); } public Set<String> getSimpleTypesUsed() { return (this.simpleTypesUsed); } public HashMap<String, CiBean> getReposiotryBeanUsed() { return (this.repositoryBeansUsed); } public HashMap<String, List<CiBean>> getDuplicatedBeans() { return (duplicatedBeans); } }