class NaiveBayes extends AbstractClassifier<Data,String> {

	@SuppressWarnings("unchecked")
	@Override
	public void learn(Data item) {

		//
		// determine the label attribute, if not already set
		//
		if( labelAttribute == null ){
			for( String name : item.keySet() )
				if( name.startsWith( "_class" ) ){
					labelAttribute = name;
					break;
				}
		}


		if( item.get( labelAttribute ) == null ){
			log.warn( "Not processing unlabeled data item {}", item );
			return;
		}

		String clazz = item.get( labelAttribute ).toString();
		log.debug( "Learning from example with label={}", clazz );
		if( this.classDistribution == null )
			this.classDistribution = new NominalDistributionModel<String>(); //this.createNominalDistribution();


		if( log.isDebugEnabled() ){
			log.debug( "Classes: {}", classDistribution.getElements() );
			for( String t : classDistribution.getElements() )
				log.debug( "    {}:  {}", t, classDistribution.getCount( t ) );
		}
		//
		// For learning we update the distributions of each attribute
		//
		for( String attribute : item.keySet() ){

			if( attribute.equalsIgnoreCase( labelAttribute ) ){
				//
				// adjust the class label distribution
				//
				classDistribution.update( clazz );

			} else {

				Object obj = item.get( attribute );

				if( obj.getClass().equals( Double.class ) ){
					Double value = (Double) obj;
					log.debug( "Handling numerical case ({}) with value  {}", obj, value );
					//
					// manage the case of an numerical attribute
					//
					Distribution<Double> numDist = (Distribution<Double>) distributions.get( attribute );
					if( numDist == null ){
						numDist = this.createNumericalDistribution();
						log.debug( "Creating new numerical distribution model for attribute {}", attribute );
						distributions.put( attribute, numDist );
					}
					numDist.update( value );

				} else {

					String value = this.getNominalCondition( attribute, item );
					log.debug( "Handling nominal case for [ {} | {} ]", value, "class=" + clazz );

					//
					// adapt the nominal distribution for this attribute
					//
					Distribution<String> nomDist = (Distribution<String>) distributions.get( clazz );
					if( nomDist == null ){
						nomDist = this.createNominalDistribution();
						log.debug( "Creating new nominal distribution model for attribute {}, {}", attribute, "class=" + clazz );
						distributions.put( clazz, nomDist );
					}
					nomDist.update( value );
				}
			}
		}
	}

	public  NaiveBayes();
	public  NaiveBayes( String labelAttribute );

}