/**
* Copyright 2007-2008 University Of Southern California
*
* Licensed 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 edu.isi.pegasus.planner.catalog.classes;
import edu.isi.pegasus.planner.classes.Profile;
import edu.isi.pegasus.planner.namespace.Namespace;
import edu.isi.pegasus.planner.namespace.Pegasus;
import edu.isi.pegasus.planner.namespace.Dagman;
import edu.isi.pegasus.planner.namespace.ENV;
import edu.isi.pegasus.planner.namespace.Globus;
import edu.isi.pegasus.planner.namespace.Hints;
import edu.isi.pegasus.planner.namespace.Condor;
import edu.isi.pegasus.planner.namespace.Metadata;
import edu.isi.pegasus.planner.namespace.Stat;
import edu.isi.pegasus.planner.namespace.Selector;
import java.util.List;
import java.util.EnumMap;
import java.util.Iterator;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Maintains profiles for different namespaces.
*
* @author Karan Vahi
* @version $Revision$
*/
public class Profiles {
/**
* The enumeration of valid namespaces. It should be
*/
public static enum NAMESPACES {
env, globus, condor, dagman, pegasus, hints, metadata, selector,stat
};
/**
* An enum map that associates the enum keys with the corresponding
* namespace objects.
*/
private EnumMap<NAMESPACES,Namespace> mProfileMap;
/**
* The default constructor.
*/
public Profiles() {
mProfileMap = new EnumMap<NAMESPACES, Namespace>( NAMESPACES.class );
mProfileMap.put( NAMESPACES.condor, new Condor() );
mProfileMap.put( NAMESPACES.dagman, new Dagman() );
mProfileMap.put( NAMESPACES.env, new ENV() );
mProfileMap.put( NAMESPACES.globus, new Globus() );
mProfileMap.put( NAMESPACES.hints, new Hints() );
mProfileMap.put( NAMESPACES.pegasus, new Pegasus() );
mProfileMap.put( NAMESPACES.selector, new Selector() );
mProfileMap.put( NAMESPACES.stat, new Stat() );
mProfileMap.put( NAMESPACES.metadata, new Metadata() );
}
/**
* Adds multiple profiles.
*
* @param profiles the profiles object
*/
public void addProfiles( Profiles profiles ) {
//traverse through all the enum keys
for ( NAMESPACES n : NAMESPACES.values() ){
Namespace nm = profiles.get( n );
for( Iterator it = nm.getProfileKeyIterator(); it.hasNext(); ){
String key = (String) it.next();
this.addProfile( new Profile( n.toString(), key, (String)nm.get( key ) ));
}
}
}
/**
* Adds multiple profiles.
*
* @param profiles List of <code>Profile</code> objects.
*/
public void addProfiles( List<Profile> profiles ) {
for( Profile profile: profiles ){
this.addProfile( profile );
}
}
/**
* Adds multiple profiles . to namespace bypassing any underlying namespace
* specific checks. The catalog parsers should use this function
*
* @param profiles the profiles object
*/
public void addProfilesDirectly( Profiles profiles ) {
//traverse through all the enum keys
for ( NAMESPACES n : NAMESPACES.values() ){
Namespace nm = profiles.get( n );
for( Iterator it = nm.getProfileKeyIterator(); it.hasNext(); ){
String key = (String) it.next();
this.addProfileDirectly( new Profile( n.toString(), key, (String)nm.get( key ) ));
}
}
}
/**
* Adds multiple profiles to namespace bypassing any underlying namespace
* specific checks. The catalog parsers should use this function.
*
*
* @param profiles List of <code>Profile</code> objects.
*/
public void addProfilesDirectly( List<Profile> profiles ) {
for ( Profile profile : profiles ){
this.addProfileDirectly( profile);
}
}
/**
* Adds a profile directly to namespace bypassing any underlying namespace
* specific checks. The catalog parsers should use this function.
*
* @param p the profile to be added
*/
public void addProfileDirectly( Profile p ){
//retrieve the appropriate namespace and then add
Namespace n = ( Namespace )mProfileMap.get( NAMESPACES.valueOf( p.getProfileNamespace() ) );
n.construct( p.getProfileKey(), p.getProfileValue() );
}
/**
* Adds a profile.
*
* @param p the profile to be added
*/
public void addProfile( Profile p ){
//retrieve the appropriate namespace and then add
Namespace n = ( Namespace )mProfileMap.get( NAMESPACES.valueOf( p.getProfileNamespace() ) );
n.checkKeyInNS( p.getProfileKey(), p.getProfileValue() );
}
/**
* Add a profile. Convenience method
* @param namespace
* @param key
* @param value
*/
public void addProfileDirectly( NAMESPACES namespace, String key, String value ){
//retrieve the appropriate namespace and then add
Namespace n = ( Namespace )mProfileMap.get(namespace);
n.construct(key,value);
}
/**
* Add a profile. Convenience method
* @param namespace
* @param key
* @param value
*/
public void addProfileDirectly( String namespace, String key, String value ){
//retrieve the appropriate namespace and then add
Namespace n = ( Namespace )mProfileMap.get(namespace);
n.construct(key,value);
}
/**
* Add a profile. Convenience method
* @param namespace
* @param key
* @param value
*/
public void addProfile( NAMESPACES namespace, String key, String value ){
//retrieve the appropriate namespace and then add
Namespace n = ( Namespace )mProfileMap.get(namespace);
n.checkKeyInNS(key,value);
}
/**
* Add a profile. Convenience method
* @param namespace
* @param key
* @param value
*/
public void addProfile( String namespace, String key, String value ){
//retrieve the appropriate namespace and then add
Namespace n = ( Namespace )mProfileMap.get(namespace);
n.checkKeyInNS(key,value);
}
/**
* Returns the list of profiles for all namespaces.
*
* @return List of <code>Profiles</code>
*/
public List<Profile> getProfiles( ){
List<Profile> result = new LinkedList();
//traverse through all the enum keys
for ( NAMESPACES n : NAMESPACES.values() ){
Namespace nm = this.get( n );
for( Iterator it = nm.getProfileKeyIterator(); it.hasNext(); ){
String key = ( String )it.next();
result.add( new Profile( n.toString(), key, (String)nm.get( key ) ));
}
}
return result;
}
/**
* Returns the list of profiles corresponding to a single namespace
*
* @param namespace the namespace
*
* @return List of <code>Profiles</code>
*/
public List<Profile> getProfiles( String namespace ){
return this.getProfiles( NAMESPACES.valueOf( namespace.toLowerCase() ));
}
/**
* Returns the list of profiles corresponding to a single namespace
*
* @param namespace the namespace
*
* @return List of <code>Profiles</code>
*/
public List<Profile> getProfiles( NAMESPACES namespace ){
return this.getProfiles( this.get(namespace) );
}
/**
* Returns the list of profiles corresponding to a single namespace
*
* @param namespace the namespace
*
* @return List of <code>Profiles</code>
*/
public List<Profile> getProfiles( Namespace namespace ){
List<Profile> result = new LinkedList();
for( Iterator it = namespace.getProfileKeyIterator(); it.hasNext(); ){
String key = ( String )it.next();
result.add( new Profile( namespace.namespaceName(), key, (String)namespace.get( key ) ));
}
return result;
}
/**
* Returns a iterator over the profile keys corresponding to a particular namespace.
*
* @param n the namespace
*
* @return iterator
*/
public Iterator getProfileKeyIterator( NAMESPACES n ){
return (( Namespace )mProfileMap.get( n )).getProfileKeyIterator();
}
/**
* Returns the namespace object corresponding to a namespace
*
* @param n the namespace
*
* @return Namespace
*/
public Namespace get( NAMESPACES n ){
return ( Namespace )mProfileMap.get( n );
}
/**
* Returns a boolean indicating if the object is empty.
*
* The object is empty if all the underlying profile maps are empty.
*
* @return
*/
public boolean isEmpty(){
boolean result = true;
for ( NAMESPACES n : NAMESPACES.values() ){
if( !this.get( n ).isEmpty() ){
result = false;
break;
}
}
return result;
}
/**
* Writes out the xml description of the object.
*
* @param writer is a Writer opened and ready for writing. This can also
* be a StringWriter for efficient output.
* @param indent the indent to be used.
*
* @exception IOException if something fishy happens to the stream.
*/
public void toXML( Writer writer, String indent ) throws IOException {
String newLine = System.getProperty( "line.separator", "\r\n" );
//traverse through all the enum keys
for ( NAMESPACES n : NAMESPACES.values() ){
Namespace nm = this.get( n );
for( Iterator it = nm.getProfileKeyIterator(); it.hasNext(); ){
String key = ( String )it.next();
//write out the xml element
writer.write( indent );
writer.write( "<profile" );
writeAttribute( writer, "namespace", n.toString() );
writeAttribute( writer, "key", key );
writer.write( " >" );
writer.write( (String)nm.get( key ) );
writer.write( "</profile>" );
writer.write( newLine );
}
}
}
/**
* Returns the string description of the object.
*
* @return String containing the object in XML.
*
* @throws RuntimeException if something fishy happens to the stream.
*/
public String toString() {
try {
Writer writer = new StringWriter(32);
toString(writer, "");
return writer.toString();
} catch (IOException ex) {
throw new RuntimeException( "Exception while converting to String", ex );
}
}
/**
* Writes out the contents of the object as a String
*
* @param writer is a Writer opened and ready for writing. This can also
* be a StringWriter for efficient output.
* @param indent the indent to be used.
*
* @exception IOException if something fishy happens to the stream.
*/
public void toString( Writer writer, String indent ) throws IOException {
String newLine = System.getProperty( "line.separator", "\r\n" );
//traverse through all the enum keys
for ( NAMESPACES n : NAMESPACES.values() ){
Namespace nm = this.get( n );
for( Iterator it = nm.getProfileKeyIterator(); it.hasNext(); ){
String key = ( String )it.next();
//write out the xml element
writer.write( indent );
writer.write( "profile" );
writer.write( " " );writer.write( n.toString() );
writer.write( " " );writer.write ( key );
writer.write( " " );writer.write( (String)nm.get( key ) );
writer.write( newLine );
}
}
}
/**
* Returns the clone of the object.
*
* @return the clone
*/
public Object clone(){
Profiles obj;
obj = new Profiles();
//traverse through all the enum keys
for ( NAMESPACES n : NAMESPACES.values() ){
Namespace nm = this.get( n );
nm = ( Namespace )this.get( n ).clone();
obj.mProfileMap.put( n, nm );
}
return obj;
}
/**
* Returns the xml description of the object. This is used for generating
* the partition graph. That is no longer done.
*
* @return String containing the object in XML.
*
* @exception IOException if something fishy happens to the stream.
*/
public String toXML() throws IOException{
Writer writer = new StringWriter(32);
toXML( writer, "" );
return writer.toString();
}
/**
* Writes an attribute to the stream. Wraps the value in quotes as required
* by XML.
*
* @param writer
* @param key
* @param value
*
* @exception IOException if something fishy happens to the stream.
*/
public void writeAttribute( Writer writer, String key, String value ) throws IOException{
writer.write( " " );
writer.write( key );
writer.write( "=\"");
writer.write( value );
writer.write( "\"" );
}
/**
* Returns the index for the namespace.
*
* @param u the unit
* @return the index.
*/
private int getIndex( NAMESPACES u ){
return u.ordinal();
}
/**
*
* @param args
*/
public static void main ( String[] args ){
try {
Profiles p = new Profiles();
p.addProfile(new Profile("pegasus", "gridstart", "none"));
p.addProfile(new Profile("env", "PEGASUS_HOME", "/pegasus"));
p.addProfile(new Profile("env", "GLOBUS_LOCATION", "GLOBUS_LOCATION"));
System.out.println("Profiles are " + p.toXML());
} catch (IOException ex) {
Logger.getLogger(Profiles.class.getName()).log(Level.SEVERE, null, ex);
}
}
}