/* * EuroCarbDB, a framework for carbohydrate bioinformatics * * Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * A copy of this license accompanies this distribution in the file LICENSE.txt. * * 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 Lesser General Public License * for more details. * * Last commit: $Rev: 1210 $ by $Author: glycoslave $ on $Date:: 2009-06-12 #$ */ package org.eurocarbdb.sugar.impl; // import java.util.Set; // import java.util.HashSet; import java.util.BitSet; import java.util.EnumSet; import org.apache.log4j.Logger; import org.eurocarbdb.sugar.Anomer; import org.eurocarbdb.sugar.Linkage; import org.eurocarbdb.sugar.LinkageType; import org.eurocarbdb.sugar.SugarSequence; import org.eurocarbdb.sugar.SequenceFormat; // import org.eurocarbdb.sugar.GlycosidicLinkage; import static org.eurocarbdb.util.JavaUtils.checkNotNull; public class LinkageDisjunction //implements Linkage { /** logging handle */ static Logger log = Logger.getLogger( LinkageDisjunction.class ); /** bitmask of parent-side (non-reducing) terminal positions. */ private BitSet parentTerminii = new BitSet( 8 ); /** bitmask of child-side (reducing) terminal positions. */ private BitSet childTerminii = new BitSet( 8 ); /** bitmask of linkage types */ private EnumSet<LinkageType> linkageTypes = EnumSet.noneOf( LinkageType.class ); public LinkageDisjunction() { } public LinkageDisjunction( Linkage... linkages ) { for ( Linkage lk : linkages ) { add( lk ); } } public void add( Linkage lk ) { checkNotNull( lk ); // monitor for linkages that may already be in this alternate boolean warrants_changes = false; /* // resolve potential anomer conflicts - // if anomers don't match, anomer becomes unknown if ( anomer == null ) { will_change = true; anomer = lk.getAnomer(); } else { if ( anomer != lk.getAnomer() ) { will_change = true; anomer = Anomer.Unknown; } } */ // check linkage types LinkageType type = lk.getLinkageType(); if ( ! linkageTypes.contains( type ) ) warrants_changes = true; // check terminii to see if different int p = lk.getParentTerminus(); int c = lk.getChildTerminus(); if ( ! (parentTerminii.get(p) && childTerminii.get(c)) ) warrants_changes = true; if ( warrants_changes ) { // add terminii parentTerminii.set( p ); childTerminii.set( c ); // add linkage type linkageTypes.add( type ); } else { // not sure that adding a duplicate linkage is a big deal, // just warn for now. /* throw new throw new IllegalArgumentException( "Linkage '" + lk + "' already exists in linkage alternate '" + this + "': cannot add duplicates" ); */ log.warn( "duplicate linkage '" + lk + "' being added to alternate" ); } } private int parentTerminus = 0; private int childTerminus = 0; public int getParentTerminus() { return (parentTerminii.cardinality() == 1) ? parentTerminii.length() - 1 : Linkage.Unknown_Terminus; } public int getChildTerminus() { return (childTerminii.cardinality() == 1) ? childTerminii.length() - 1 : Linkage.Unknown_Terminus; } public LinkageType getLinkageType() { return null; } public int[] getParentTerminii() { return _bitset_to_list( parentTerminii ); } public int[] getChildTerminii() { return _bitset_to_list( childTerminii ); } /** Returns current number of linkage alternates */ public int size() { int size = parentTerminii.cardinality() + childTerminii.cardinality() - 2; return ( size < 0 ) ? 0 : size; } /* public String toString() { StringBuffer sb = new StringBuffer(); sb.append( join("|", linkageTypes ) ); sb.append( join("|", getParentTerminii() ) ); sb.append('-'); sb.append( join("|", getChildTerminii() ) ); return join("|", alternates ); } */ // private methods private final int[] _bitset_to_list( BitSet bs ) { int[] terminii = new int[ parentTerminii.cardinality() ]; int i = 0; int term = bs.nextSetBit(0); for( ; term >= 0; term = bs.nextSetBit( term + 1 ) ) terminii[i++] = term; return terminii; } }