Builds the MBeanInfo for all the exposed attributes.

@throws IntrospectionException
496658
private void buildMBeanInfo() throws IntrospectionException
    {
        if( m_mode == Mode.JMX_ONLY || m_mode == Mode.ALL )
        {
            MBeanAttributeInfo[] attributes = null;

            int numAttrs = m_jmxAttributes != null ? m_jmxAttributes.length : 0;

            int numItems = CONSTANT_ATTRS_PER_ITEM + m_percentiles.length;

            attributes = new MBeanAttributeInfo[numAttrs*numItems+5];

            if( m_jmxAttributes != null )
            {
                for( int i = 0; i < m_jmxAttributes.length; i++ )
                {
                    String name = m_jmxAttributes[i].trim();

                    attributes[numItems*i]   = new MBeanAttributeInfo( name+ATTR_POSTFIX_AVG,    "double", "Average value (in milliseconds)", true, false, false );
                    attributes[numItems*i+1] = new MBeanAttributeInfo( name+ATTR_POSTFIX_STDDEV, "double", "Standard Deviation", true, false, false );
                    attributes[numItems*i+2] = new MBeanAttributeInfo( name+ATTR_POSTFIX_MIN,    "double", "Minimum value", true, false, false );
                    attributes[numItems*i+3] = new MBeanAttributeInfo( name+ATTR_POSTFIX_MAX,    "double", "Maximum value", true, false, false );
                    attributes[numItems*i+4] = new MBeanAttributeInfo( name+ATTR_POSTFIX_COUNT,  "int",    "Number of invocations", true, false, false );

                    //
                    //  Generate the percentile titles as /<perc>
                    //  Drops the fractions if they're zero.
                    //  TODO: There's probably a prettier way to do this.
                    //
                    for( int p = 0; p < m_percentiles.length; p++ )
                    {
                        String perTitle = saneDoubleToString( m_percentiles[p] );

                        attributes[numItems*i+5+p] = new MBeanAttributeInfo( name+"/"+perTitle,  "double", perTitle+"th percentile", true, false, false );
                    }
                }

            }

            //
            //  Add internal management attributes if there's a need for
            //  JMX
            //
            attributes[attributes.length-1] = new MBeanAttributeInfo( JMX_QUEUE_LENGTH, "int",
                                                                      "Current StopWatch processing queue length (i.e. how many StopWatches are currently unprocessed)",
                                                                      true, false, false );

            attributes[attributes.length-2] = new MBeanAttributeInfo( JMX_DROPPED_STOPWATCHES, "long",
                                                                      "How many StopWatches have been dropped due to processing restrictions",
                                                                      true, false, false );

            attributes[attributes.length-3] = new MBeanAttributeInfo( JMX_PERIOD_SECONDS, "int",
                                                                      "Current logging period (seconds)",
                                                                      true, true, false );

            attributes[attributes.length-4] = new MBeanAttributeInfo( JMX_SLOW_LOG_PERCENTILE, "double",
                                                                      "Which percentile gets logged to slowlog",
                                                                      true, true, false );

            attributes[attributes.length-5] = new MBeanAttributeInfo( JMX_SLOW_LOG_TOGGLE, "boolean",
                                                                      "Is slow logging on?",
                                                                      true, true, false );

            //
            //  Create the actual BeanInfo instance.
            //
            MBeanOperationInfo[] operations = null;
            MBeanConstructorInfo[] constructors = null;
            MBeanNotificationInfo[] notifications = null;

            m_beanInfo = new MBeanInfo( getClass().getName(),
                                        "PeriodicalLog for logger "+getName(),
                                        attributes,
                                        constructors,
                                        operations,
                                        notifications );
        }
        else
        {
            m_beanInfo = null;
        }

    }
295037
public Map<String, MBeanAttributeInfo> getAttributeMetadata() {

        MBeanAttributeInfo[] attributeList = mBeanInfo.getAttributes();

        Map<String, MBeanAttributeInfo> attributeMap = new TreeMap<String, MBeanAttributeInfo>();
        for (MBeanAttributeInfo attribute: attributeList) {
            attributeMap.put(attribute.getName(), attribute);
        }
        return attributeMap;
    }
559493
@Override
	public final MBeanInfo getMBeanInfo() {
		final MBeanOperationInfo[] opers = createMBeanOperationInfo();
		return new MBeanInfo(remoteProgram.getAdapterClass().getCanonicalName(), null, null, null, opers, null);
	}
582990
@SuppressWarnings("unchecked")
    private PropertyDescriptor[] introspectProperties(Class<?> stopClass)
            throws IntrospectionException {

        // Get descriptors for the public methods
        MethodDescriptor[] methodDescriptors = introspectMethods();

        if (methodDescriptors == null) {
            return null;
        }

        ArrayList<MethodDescriptor> methodList = new ArrayList<MethodDescriptor>();
        // Loop over the methods found, looking for public non-static methods
        for (int index = 0; index < methodDescriptors.length; index++) {
            int modifiers = methodDescriptors[index].getMethod().getModifiers();
            if (!Modifier.isStatic(modifiers)) {
                methodList.add(methodDescriptors[index]);
            }
        }

        // Get the list of public non-static methods into an array
        int methodCount = methodList.size();
        MethodDescriptor[] theMethods = null;
        if (methodCount > 0) {
            theMethods = new MethodDescriptor[methodCount];
            theMethods = methodList.toArray(theMethods);
        }

        if (theMethods == null) {
            return null;
        }

        HashMap<String, HashMap> propertyTable = new HashMap<String, HashMap>(
                theMethods.length);

        // Search for methods that either get or set a Property
        for (int i = 0; i < theMethods.length; i++) {
            introspectGet(theMethods[i].getMethod(), propertyTable);
            introspectSet(theMethods[i].getMethod(), propertyTable);
        }

        // fix possible getter & setter collisions
        fixGetSet(propertyTable);

        // If there are listener methods, should be bound.
        MethodDescriptor[] allMethods = introspectMethods(true);
        if (stopClass != null) {
            MethodDescriptor[] excludeMethods = introspectMethods(true,
                    stopClass);
            if (excludeMethods != null) {
                ArrayList<MethodDescriptor> tempMethods = new ArrayList<MethodDescriptor>();
                for (MethodDescriptor method : allMethods) {
                    if (!isInSuper(method, excludeMethods)) {
                        tempMethods.add(method);
                    }
                }
                allMethods = tempMethods
                        .toArray(new MethodDescriptor[0]);
            }
        }
        for (int i = 0; i < allMethods.length; i++) {
            introspectPropertyListener(allMethods[i].getMethod());
        }
        // Put the properties found into the PropertyDescriptor array
        ArrayList<PropertyDescriptor> propertyList = new ArrayList<PropertyDescriptor>();

        for (Map.Entry<String, HashMap> entry : propertyTable.entrySet()) {
            String propertyName = entry.getKey();
            HashMap table = entry.getValue();
            if (table == null) {
                continue;
            }
            String normalTag = (String) table.get(STR_NORMAL);
            String indexedTag = (String) table.get(STR_INDEXED);

            if ((normalTag == null) && (indexedTag == null)) {
                continue;
            }

            Method get = (Method) table.get(STR_NORMAL + PREFIX_GET);
            Method set = (Method) table.get(STR_NORMAL + PREFIX_SET);
            Method indexedGet = (Method) table.get(STR_INDEXED + PREFIX_GET);
            Method indexedSet = (Method) table.get(STR_INDEXED + PREFIX_SET);

            PropertyDescriptor propertyDesc = null;
            if (indexedTag == null) {
                propertyDesc = new PropertyDescriptor(propertyName, get, set);
            } else {
                try {
                    propertyDesc = new IndexedPropertyDescriptor(propertyName,
                            get, set, indexedGet, indexedSet);
                } catch (IntrospectionException e) {
                    // If the getter and the indexGetter is not compatible, try
                    // getter/setter is null;
                    propertyDesc = new IndexedPropertyDescriptor(propertyName,
                            null, null, indexedGet, indexedSet);
                }
            }
            // RI set propretyDescriptor as bound. FIXME
            // propertyDesc.setBound(true);
            if (canAddPropertyChangeListener && canRemovePropertyChangeListener) {
                propertyDesc.setBound(true);
            } else {
                propertyDesc.setBound(false);
            }
            if (table.get(STR_IS_CONSTRAINED) == Boolean.TRUE) { //$NON-NLS-1$
                propertyDesc.setConstrained(true);
            }
            propertyList.add(propertyDesc);
        }

        PropertyDescriptor[] theProperties = new PropertyDescriptor[propertyList
                .size()];
        propertyList.toArray(theProperties);
        return theProperties;
    }
260458
@SuppressWarnings("unchecked")
    private Map<String,Object> jsonifyMBeanInfo(MBeanInfo mBeanInfo) {
        Map<String, Object> result = new LinkedHashMap<>();

        // desc
        result.put("desc", mBeanInfo.getDescription());

        // attr
        Map<String, Object> attrMap = new LinkedHashMap<>();
        result.put("attr", attrMap);
        for (MBeanAttributeInfo attrInfo : mBeanInfo.getAttributes()) {
            if (attrInfo == null) {
                continue;
            }
            Map<String, Object> attr = new HashMap<>();
            attr.put("type", attrInfo.getType());
            attr.put("desc", attrInfo.getDescription());
            attr.put("rw", attrInfo.isWritable() && attrInfo.isReadable());
            attrMap.put(attrInfo.getName(), attr);
        }

        // op
        Map<String, Object> opMap = new LinkedHashMap<>();
        result.put("op", opMap);
        for (MBeanOperationInfo opInfo : mBeanInfo.getOperations()) {
            Map<String, Object> map = new HashMap<>();
            List<Map<String, String>> argList = new ArrayList<>(opInfo.getSignature().length);
            for (MBeanParameterInfo paramInfo : opInfo.getSignature()) {
                Map<String, String> args = new HashMap<>();
                args.put("desc", paramInfo.getDescription());
                args.put("name", paramInfo.getName());
                args.put("type", paramInfo.getType());
                argList.add(args);
            }
            map.put("args", argList);
            map.put("ret", opInfo.getReturnType());
            map.put("desc", opInfo.getDescription());
            Object ops = opMap.get(opInfo.getName());
            if (ops != null) {
                if (ops instanceof List) {
                    // If it is already a list, simply add it to the end
                    ((List) ops).add(map);
                } else if (ops instanceof Map) {
                    // If it is a map, add a list with two elements
                    // (the old one and the new one)
                    List<Object> opList = new LinkedList<>();
                    opList.add(ops);
                    opList.add(map);
                    opMap.put(opInfo.getName(), opList);
                }
            } else {
                // No value set yet, simply add the map as plain value
                opMap.put(opInfo.getName(), map);
            }
        }

        // not
        Map<String, Object> notMap = new LinkedHashMap<>();
        result.put("not", notMap);
        for (MBeanNotificationInfo notInfo : mBeanInfo.getNotifications()) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", notInfo.getName());
            map.put("desc", notInfo.getDescription());
            String[] types = notInfo.getNotifTypes();
            List<String> tList = new ArrayList<>(types.length);
            Collections.addAll(tList, types);
            map.put("types", tList);
            notMap.put(notInfo.getName(), map);
        }

        // this is default - in case we won't find RBACDecorator (possible in hawtio-wildfly for example)
        result.put("canInvoke", true);

        return result;
    }
575654
private void introspect() {
    // Make sure the class is Embeddable
    if (!embeddableClass.isAnnotationPresent(Embeddable.class)) {
      String message = String.format("Class %s must have %s annotation", embeddableClass.getName(),
          Embeddable.class.getName());
      throw new EntityManagerException(message);
    }
    metadata = new EmbeddableMetadata(embeddableClass);
    processFields();
  }
393582
@Override
    public String[] introspectSelf() {
        List<?> nameValuePairs = Arrays.asList(
                                               BEGIN_TRAN_FOR_SCROLLING_APIS, beginTranForResultSetScrollingAPIs,
                                               BEGIN_TRAN_FOR_VENDOR_APIS, beginTranForVendorAPIs,
                                               COMMIT_OR_ROLLBACK_ON_CLEANUP, commitOrRollbackOnCleanup,
                                               CONNECTION_SHARING, connectionSharing,
                                               DataSourceDef.isolationLevel.name(), isolationLevel,
                                               ResourceFactory.JNDI_NAME, jndiName,
                                               ENABLE_CONNECTION_CASTING, enableConnectionCasting,
                                               QUERY_TIMEOUT, queryTimeout,
                                               STATEMENT_CACHE_SIZE, statementCacheSize,
                                               SUPPLEMENTAL_JDBC_TRACE, supplementalJDBCTrace,
                                               SYNC_QUERY_TIMEOUT_WITH_TRAN_TIMEOUT, syncQueryTimeoutWithTransactionTimeout,
                                               DataSourceDef.transactional.name(), transactional
                                               );
        return new String[] {
                             toString(),
                             nameValuePairs.toString(),
                             PropertyService.hidePasswords(vendorProps).toString() };
    }
617393
@Override
    public String[] introspectSelf() {
        String[] debugInfo = new String[6];
        debugInfo[0] = "JSMessageData:";

        // Include the basic toString info so we know who we are
        StringBuilder sb = new StringBuilder("Self: ");
        sb.append(toString());
        debugInfo[1] = new String(sb);

        // Include the cache information
        sb.setLength(0);
        sb.append("Cache: size=");
        sb.append(cacheSize);
        sb.append(" cache=");
        sb.append(cache); // Yes we really do just want [Ljava.lang.Object;@xxxxxx here
        debugInfo[2] = new String(sb);

        // Include the cache information
        sb.setLength(0);
        sb.append("Contents: ");
        if (contents == null) {
            sb.append("null");
        }
        else {
            sb.append("size=");
            sb.append(contents.length);
            sb.append(" contents=");
            sb.append(contents); // Yes we really do just want [B@xxxxxxx here
        }
        debugInfo[3] = new String(sb);

        // Include sharing information
        sb.setLength(0);
        sb.append("Sharing: sharedCache=");
        sb.append(sharedCache);
        sb.append(" sharedContents=");
        sb.append(sharedContents);
        debugInfo[4] = new String(sb);

        // Include all the stuff abot how it fits in to the heirarchy
        sb.setLength(0);
        sb.append("Context: parentMessage=");
        sb.append(parentMessage);
        sb.append(" containingMessage=");
        sb.append(containingMessage);
        sb.append(" master=");
        if (master == this) {
            sb.append("self");
        }
        else {
            sb.append(master);
        }
        sb.append(" compatibilityWrapperOrSelf=");
        if (compatibilityWrapperOrSelf == this) {
            sb.append("self");
        }
        else {
            sb.append(compatibilityWrapperOrSelf);
        }
        debugInfo[5] = new String(sb);

        // Now return it all
        return debugInfo;
    }
689917
private void initOpenMBeanInfo() {
        OpenMBeanAttributeInfoSupport[] attributes = new OpenMBeanAttributeInfoSupport[4];
        OpenMBeanConstructorInfoSupport[] constructors = new OpenMBeanConstructorInfoSupport[1];
        OpenMBeanOperationInfoSupport[] operations = new OpenMBeanOperationInfoSupport[2];
        MBeanNotificationInfo[] notifications = new MBeanNotificationInfo[0];

        try {
            // Define the attributes 
            attributes[0] = new OpenMBeanAttributeInfoSupport(ATTR_ID,
                                                              "Knowledge Base Id",
                                                              SimpleType.STRING,
                                                              true,
                                                              false,
                                                              false);
            attributes[1] = new OpenMBeanAttributeInfoSupport(ATTR_SESSION_COUNT,
                                                              "Number of created sessions for this Knowledge Base",
                                                              SimpleType.LONG,
                                                              true,
                                                              false,
                                                              false);
            attributes[2] = new OpenMBeanAttributeInfoSupport(ATTR_GLOBALS,
                                                              "List of globals",
                                                               globalsTableType,
                                                               true,
                                                               false,
                                                               false );
            attributes[3] = new OpenMBeanAttributeInfoSupport( ATTR_PACKAGES,
                                                               "List of Packages",
                                                               new ArrayType( 1,
                                                                              SimpleType.STRING ),
                                                               true,
                                                               false,
                                                               false );
            //No arg constructor                
            constructors[0] = new OpenMBeanConstructorInfoSupport( "KnowledgeBaseMonitoringMXBean",
                                                                   "Constructs a KnowledgeBaseMonitoringMXBean instance.",
                                                                   new OpenMBeanParameterInfoSupport[0] );
            //Operations 
            OpenMBeanParameterInfo[] params = new OpenMBeanParameterInfoSupport[0];
            operations[0] = new OpenMBeanOperationInfoSupport( OP_START_INTERNAL_MBEANS,
                                                               "Creates, registers and starts all the dependent MBeans that allow monitor all the details in this KnowledgeBase.",
                                                               params,
                                                               SimpleType.VOID,
                                                               MBeanOperationInfo.INFO );
            operations[1] = new OpenMBeanOperationInfoSupport( OP_STOP_INTERNAL_MBEANS,
                                                               "Stops and disposes all the dependent MBeans that allow monitor all the details in this KnowledgeBase.",
                                                               params,
                                                               SimpleType.VOID,
                                                               MBeanOperationInfo.INFO );

            //Build the info 
            info = new OpenMBeanInfoSupport( this.getClass().getName(),
                                             "Knowledge Base Monitor MXBean",
                                             attributes,
                                             constructors,
                                             operations,
                                             notifications );
        } catch ( Exception e ) {
            e.printStackTrace();
        }
    }
1337505
private void initMBean()  {
        try {
            registerMBean(this,getObjectName());
        } catch (InstanceAlreadyExistsException exp) {
            // This is no problem, since this MBeanServerHandlerMBean holds only global information
            // with no special state (so all instances of this MBean behave similar)
            // This exception can happen, when multiple servlets get registered within the same JVM
        } catch (MalformedObjectNameException e) {
            // Cannot happen, otherwise this is a bug. We should be always provide our own name in correct
            // form.
            throw new IllegalStateException("Internal Error: Own ObjectName " + getObjectName() + " is malformed",e);
        } catch (NotCompliantMBeanException e) {
            // Same here
            throw new IllegalStateException("Internal Error: " + this.getClass().getName() + " is not a compliant MBean",e);
        }
    }
1360747
private void scanMBeanAttributes(MBeanConfig mBeanConfig,
			ObjectName mBeanName) {
		MBeanInfo mBeanInfo;
		try {
			mBeanInfo = mBeanServer.getMBeanInfo(mBeanName);
			MBeanAttributeInfo[] infos = mBeanInfo.getAttributes();
			for (int i = 0; i < infos.length; i++) {
				MBeanAttributeConfig cMBAttr = makeConfigMBeanAttribute(
						mBeanName, infos[i]);
				mBeanConfig.addChild(cMBAttr);
			}
		} catch (IntrospectionException e) {
			System.err.println(e.getMessage());
		} catch (InstanceNotFoundException e) {
			System.err.println(e.getMessage());
		} catch (ReflectionException e) {
			System.err.println(e.getMessage());
		}
	}
530690
private void discoverAttributeFields(Map<String, JmxAttributeFieldInfo> attributeFieldInfoMap,
			Set<String> attributeNameSet, List<MBeanAttributeInfo> attributes) {
		for (Class<?> clazz = target.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
			discoverAttributeFields(attributeFieldInfoMap, attributeNameSet, attributes, clazz);
		}
	}
1098524
public void buildTaxonomy() {
        
        // Determine if a full or incremental calculation is required
        if(!hasBeenIncrementallyClassified) {
            buildTaxonomyConcurrent();
            //buildTaxonomySequential();
        } else {
            final IConceptMap<IConceptSet> newConceptSubs = getNewSubsumptions();
            final IConceptMap<IConceptSet> affectedConceptSubs = getAffectedSubsumptions();
            
            // 1. Keep only the subsumptions that involve real atomic concepts
            IConceptMap<IConceptSet> allNew = new SparseConceptMap<IConceptSet>(newConceptSubs.size());

            IConceptMap<IConceptSet> allAffected = new SparseConceptMap<IConceptSet>(newConceptSubs.size());

            for (IntIterator itr = newConceptSubs.keyIterator(); itr.hasNext();) {
                final int x = itr.next();
                if (!factory.isVirtualConcept(x)) {
                    IConceptSet set = new SparseConceptHashSet();
                    allNew.put(x, set);
                    for (IntIterator it = newConceptSubs.get(x).iterator(); it.hasNext();) {
                        int next = it.next();
                        if (!factory.isVirtualConcept(next)) {
                            set.add(next);
                        }
                    }
                }
            }

            for (IntIterator itr = affectedConceptSubs.keyIterator(); itr.hasNext();) {
                final int x = itr.next();
                if (!factory.isVirtualConcept(x)) {
                    IConceptSet set = new SparseConceptHashSet();
                    allAffected.put(x, set);
                    for (IntIterator it = affectedConceptSubs.get(x).iterator(); it.hasNext();) {
                        int next = it.next();
                        if (!factory.isVirtualConcept(next)) {
                            set.add(next);
                        }
                    }
                }
            }
            
            // 2. Create nodes for new concepts and connect to node hierarchy
            // a. First create the nodes and add to index
            for (IntIterator itr = allNew.keyIterator(); itr.hasNext();) {
                final String key = factory.lookupConceptId(itr.next()).toString();
                Node cn = new Node();
                cn.getEquivalentConcepts().add(key);
                conceptNodeIndex.put(key, cn);
            }

            // b. Now connect the nodes disregarding redundant connections
            Node bottomNode = conceptNodeIndex.get(au.csiro.ontology.model.NamedConcept.BOTTOM);
            for (IntIterator itr = allNew.keyIterator(); itr.hasNext();) {
                int id = itr.next();
                final String key = factory.lookupConceptId(id).toString();
                Node cn = conceptNodeIndex.get(key);
                IConceptSet parents = allNew.get(id);
                for (IntIterator itr2 = parents.iterator(); itr2.hasNext();) {
                    // Create a connection to each parent
                    int parentId = itr2.next();
                    if (parentId == id)
                        continue;
                    Node parent = conceptNodeIndex.get(factory.lookupConceptId(parentId));
                    cn.getParents().add(parent);
                    parent.getChildren().add(cn);
                    // All nodes that get new children and are connected to BOTTOM
                    // must be disconnected
                    if (parent.getChildren().contains(bottomNode)) {
                        parent.getChildren().remove(bottomNode);
                        bottomNode.getParents().remove(parent);
                    }
                }
            }
            
            Set<Integer> toRemoveFromAffected = new HashSet<Integer>();
            for (IntIterator itr = allAffected.keyIterator(); itr.hasNext();) {
                final int id = itr.next();
                final String key = factory.lookupConceptId(id).toString();
                Node cn = conceptNodeIndex.get(key);
                IConceptSet parents = allAffected.get(id);
                
                if(parents.contains(IFactory.BOTTOM_CONCEPT)) {
                    // Special case - bottom is parent
                    
                    // a. add equivalents to bottom node
                    bottomNode.getEquivalentConcepts().addAll(cn.getEquivalentConcepts());
                    
                    Set<Node> tempParents = cn.getParents();
                    Set<Node> tempChildren = cn.getChildren();
                    
                    // b. reconnect parents to children
                    for(Node parent : tempParents) {
                        parent.getChildren().remove(cn);
                        parent.getChildren().addAll(tempChildren);
                    }
                    
                    for(Node child : tempChildren) {
                        child.getParents().remove(cn);
                        child.getParents().addAll(tempParents);
                    }
                    
                    for(String k : cn.getEquivalentConcepts()) {
                        conceptNodeIndex.remove(k);
                        conceptNodeIndex.put(key, bottomNode);
                    }
                    toRemoveFromAffected.add(id);
                } else {
                    for (IntIterator itr2 = parents.iterator(); itr2.hasNext();) {
                        // Create a connection to each parent
                        int parentId = itr2.next();
                        if (parentId == id)
                            continue;
                        Node parent = conceptNodeIndex.get(factory.lookupConceptId(parentId));
                        cn.getParents().add(parent);
                        parent.getChildren().add(cn);
                        // All nodes that get new children and are connected to BOTTOM must be disconnected
                        if (parent.getChildren().contains(bottomNode)) {
                            parent.getChildren().remove(bottomNode);
                            bottomNode.getParents().remove(parent);
                        }
                    }
                }
            }
            
            for(Integer i : toRemoveFromAffected) {
                allAffected.remove(i.intValue());
                allNew.remove(i.intValue());
            }

            // 3. Connect new nodes without parents to TOP
            Node topNode = conceptNodeIndex.get(au.csiro.ontology.model.NamedConcept.TOP);

            for (IntIterator itr = allNew.keyIterator(); itr.hasNext();) {
                final String key = factory.lookupConceptId(itr.next()).toString();
                Node cn = conceptNodeIndex.get(key);
                if (cn.getParents().isEmpty()) {
                    cn.getParents().add(topNode);
                    topNode.getChildren().add(cn);
                }
            }

            // 4. Fix connections for new and affected concepts
            // a. Check for equivalents
            Set<Pair> pairsToMerge = new HashSet<Pair>();
            for (IntIterator itr = allNew.keyIterator(); itr.hasNext();) {
                final String key = factory.lookupConceptId(itr.next()).toString();
                Node cn = conceptNodeIndex.get(key);
                for (Node parent : cn.getParents()) {
                    if (parent.getParents().contains(cn)) {
                        pairsToMerge.add(new Pair(cn, parent));
                    }
                }
            }
            for (IntIterator itr = allAffected.keyIterator(); itr.hasNext();) {
                final String key = factory.lookupConceptId(itr.next()).toString();
                Node cn = conceptNodeIndex.get(key);
                for (Node parent : cn.getParents()) {
                    if (parent.getParents().contains(cn)) {
                        pairsToMerge.add(new Pair(cn, parent));
                    }
                }
            }

            Set<Node> affectedByMerge = new HashSet<Node>();

            // Merge equivalents
            for (Pair p : pairsToMerge) {
                Node cn1 = p.getA();
                Node cn2 = p.getB();

                affectedByMerge.addAll(cn1.getChildren());
                affectedByMerge.addAll(cn2.getChildren());

                // Merge into cn1 - remove cn2 from index and replace with cn1
                for (String n : cn2.getEquivalentConcepts()) {
                    conceptNodeIndex.put(n, cn1);
                }

                cn1.getEquivalentConcepts().addAll(cn2.getEquivalentConcepts());

                // Remove relationships between merged concepts
                cn1.getParents().remove(cn2);
                cn2.getChildren().remove(cn1);
                cn2.getParents().remove(cn1);
                cn1.getChildren().remove(cn2);

                // Taxonomy is bidirectional
                cn1.getParents().addAll(cn2.getParents());
                for (Node parent : cn2.getParents()) {
                    parent.getChildren().remove(cn2);
                    parent.getChildren().add(cn1);
                }
                cn1.getChildren().addAll(cn2.getChildren());
                for (Node child : cn2.getChildren()) {
                    child.getParents().remove(cn2);
                    child.getParents().add(cn1);
                }

                cn2 = null; // nothing should reference cn2 now
            }

            // b. Fix all new and affected nodes
            Set<Node> all = new HashSet<Node>();
            for (IntIterator it = allNew.keyIterator(); it.hasNext();) {
                all.add(conceptNodeIndex.get(factory.lookupConceptId(it.next())));
            }

            for (IntIterator it = allAffected.keyIterator(); it.hasNext();) {
                all.add(conceptNodeIndex.get(factory.lookupConceptId(it.next())));
            }

            for (Node cn : affectedByMerge) {
                all.add(cn);
            }

            // Add also the children of the affected nodes
            Set<Node> childrenToAdd = new HashSet<Node>();
            for (Node cn : all) {
                for (Node ccn : cn.getChildren()) {
                    if (ccn.equals(bottomNode))
                        continue;
                    childrenToAdd.add(ccn);
                }
            }
            all.addAll(childrenToAdd);

            // Find redundant relationships
            for (Node cn : all) {
                Set<Node> ps = cn.getParents();

                Object[] parents = ps.toArray(new Object[ps.size()]);
                Set<Node> toRemove = new HashSet<Node>();
                for (int i = 0; i < parents.length; i++) {
                    for (int j = i + 1; j < parents.length; j++) {
                        if (isChild((Node)parents[j], (Node)parents[i])) {
                            toRemove.add((Node)parents[i]);
                            continue;
                        }
                        if (isChild((Node)parents[i], (Node)parents[j])) {
                            toRemove.add((Node)parents[j]);
                            continue;
                        }
                    }
                }
                for (Node tr : toRemove) {
                    cn.getParents().remove(tr);
                    tr.getChildren().remove(cn);
                }
            }

            // 5. Connect bottom to new and affected concepts with no children
            for (IntIterator itr = allNew.keyIterator(); itr.hasNext();) {
                final int key = itr.next();
                Node cn = conceptNodeIndex.get(factory.lookupConceptId(key));
                if (cn.getChildren().isEmpty()) {
                    cn.getChildren().add(bottomNode);
                    bottomNode.getParents().add(cn);
                }
            }
            for (IntIterator itr = allAffected.keyIterator(); itr.hasNext();) {
                final int key = itr.next();
                Node cn = conceptNodeIndex.get(factory.lookupConceptId(key));
                if (cn.getChildren().isEmpty()) {
                    cn.getChildren().add(bottomNode);
                    bottomNode.getParents().add(cn);
                }
            }

            // 6. Connect the top node to new and affected concepts with no parents
            for (IntIterator itr = allNew.keyIterator(); itr.hasNext();) {
                final int key = itr.next();
                Node cn = conceptNodeIndex.get(factory.lookupConceptId(key));
                if (cn.getParents().isEmpty()) {
                    cn.getParents().add(topNode);
                    topNode.getChildren().add(cn);
                }
            }
            for (IntIterator itr = allAffected.keyIterator(); itr.hasNext();) {
                final int key = itr.next();
                Node cn = conceptNodeIndex.get(factory.lookupConceptId(key));
                if (cn.getParents().isEmpty()) {
                    cn.getParents().add(topNode);
                    topNode.getChildren().add(cn);
                }
            }
        }  
    }
342184
public BeanInfo getBeanInfo() {
        if (mBeanInfo == null) {
            try { 
                mBeanInfo = getTeaToolsUtils().getBeanInfo(mType);
            }
            catch (Exception e) {
                return null;
            }
        }

        return mBeanInfo;
    }
513484
@Override
    public String[] introspectSelf() {
        List<String> rc = new ArrayList<String>();
        rc.add(Thread.currentThread().getName());
        rc.add("selectorTimeout: " + this.selectorTimeout);
        rc.add("usageCount: " + this.usageCount);
        rc.add("quit: " + this.quit);
        rc.add("waitingToQuit: " + this.waitingToQuit);
        rc.add("firstErrorTime: " + this.firstErrorTime + "=" + new Date(this.firstErrorTime));
        rc.add("Total exceptions: " + this.numExceptions);
        rc.add("\tIOExceptions on accept: " + this.numAcceptIOExceptions);
        rc.add("\tnull sockets on accept: " + this.numAcceptNulls);
        rc.add("\tIOExceptions on configure: " + this.numConfigureIOExceptions);
        rc.add("\tnumber of cancelled keys: " + this.numCancelledKeys);

        rc.add("# of keys=" + this.selector.keys().size());
        try {
            for (SelectionKey key : this.selector.keys()) {
                rc.add("key: " + key.channel());
            }
        } catch (Throwable x) {
            // If we get any exception, just return what we have so far.
            // This routine is not thread safe, and could get an exception, but
            // since it is only invoked when we are dumping data, due to a problem or
            // during debug this should be acceptable.
            rc.add("Exception Occurred Gathering Dump Data: " + x);
        }

        return rc.toArray(new String[rc.size()]);
    }
491003
public Method[] getArrayAccessMethods() throws IntrospectionException {
        if (!mCheckedForArrayLookup) {
            checkForArrayLookup();
        }

        return mArrayAccessMethods == null ? null :
            (Method[])mArrayAccessMethods.clone();
    }
1026913
public MBeanAttributeInfo[] getAttributes() {
    final List<MBeanAttributeInfo> attributes = new ArrayList<MBeanAttributeInfo>();
    for (int i = 1; i <= reportable.getMaxEntriesToKeep(); i++) {
      attributes.add(new MBeanAttributeInfo(Integer.toString(i), "String", "Value number " + i + " in history", true,
          false, false));
    }
    return attributes.toArray(new MBeanAttributeInfo[attributes.size()]);
  }