001/*
002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003 * Copyright (C) 2006 - JScience (http://jscience.org/)
004 * All rights reserved.
005 * 
006 * Permission to use, copy, modify, and distribute this software is
007 * freely granted, provided that this notice is preserved.
008 */
009package org.jscience.physics.model;
010
011import javax.measure.converter.UnitConverter;
012import javax.measure.unit.BaseUnit;
013import javax.measure.unit.Dimension;
014
015import javolution.context.LocalContext;
016
017/**
018 * <p> This abstract class represents a physical model. Instances of this
019 *     class determinate the current quantities dimensions.</p>
020 *     
021 * <p> To select a model, one needs only to call the model <code>select</code>
022 *     static method. For example:[code]
023 *     public static void main(String[] args) {
024 *          // Global (LocalContext should be used for thread-local settings).
025 *          RelativisticModel.select();
026 *          ...
027 *     [/code]</p>
028 *     
029 * <p> Selecting a predefined model automatically sets the dimension of 
030 *     the {@link javax.measure.unit.BaseUnit base units}.</p>
031 *
032 * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
033 * @version 3.1, April 22, 2006
034 */
035public abstract class PhysicalModel implements Dimension.Model {
036
037    /**
038     * Holds the current physical model.
039     */
040    private static LocalContext.Reference<PhysicalModel> Current 
041        = new LocalContext.Reference<PhysicalModel>();
042    
043    /**
044     * Holds the dimensional model.
045     */
046    private static final Dimension.Model DIMENSIONAL_MODEL 
047        = new Dimension.Model() {
048
049            public Dimension getDimension(BaseUnit<?> unit) {
050                return PhysicalModel.Current.get().getDimension(unit);
051            }
052
053            public UnitConverter getTransform(BaseUnit<?> unit) {
054                return PhysicalModel.Current.get().getTransform(unit);
055            }};
056    
057    /**
058     * Default constructor (allows for derivation).
059     */
060    protected PhysicalModel() {
061    }
062
063    /**
064     * Returns the current physical model (default: instance of 
065     * {@link StandardModel}).
066     *
067     * @return the context-local physical model.
068     */
069    public static final PhysicalModel current() {
070        PhysicalModel physicalModel = PhysicalModel.Current.get();
071        return (physicalModel == null) ? StandardModel.INSTANCE : physicalModel;
072    }
073
074    /**
075     * Sets the current model (this method is called when the a predefined 
076     * model is selected).
077     *
078     * @param  model the context-local physical model.
079     * @see    #current
080     */
081    protected static final void setCurrent(PhysicalModel model) {
082        PhysicalModel.Current.set(model);
083        Dimension.setModel(DIMENSIONAL_MODEL);
084    }
085
086}