text:
package org.hbird.business.validation.bean;

import org.apache.camel.Body;
import org.hbird.exchange.core.Parameter;
import org.hbird.exchange.core.State;
import org.hbird.exchange.validation.Limit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The baselimit is an abstract base class for all limit check types. It
 * holds all methods to receive messages through camel routes and
 * parse them on, i.e. it is a camel processor bean.
 *
 * A limit bean transform a parameter value into a parameter state value, i.e.
 * it validates whether the parameter is within the limit and sends a corresponding
 * a parameter state value of 'true' (state is in limit) or false (outside limit).
 *
 * A specific limit instance is configured through
 * - StateName. The name of the state parameter that this limit will issue.
 * - Enabled. A parameter setting whether this limit is enabled or disabled.
 * - limit. The actual limit to be validated against.
 * - parameter. The last received parameter value.
 *
 * The state name is defined at creation, where as the enabled, limit and parameter values
 * are dynamically updated through camel updates. Three camel routes are defined into the bean;
 * - processParameter. Processes a camel Exchange containing a parameter instance to be limit checked.
 * - processLimit. Process a camel Exchange containing an update to the limit value.
 * - processEnabled. Process a camel Exchange enabling / disabling this limit.
 *
 */
public abstract class BaseLimitChecker {

    /** The class logger. */
    private static Logger logger = LoggerFactory.getLogger(BaseLimitChecker.class);

    /** The limit definition. */
    protected Limit limit = null;

    /**
     * The last received parameter to be checked. Stored in case the limit is changed or the
     * limit is enabled. Then the last received value is used to re-check the limit.
     */
    protected Parameter lastValue = null;

    public BaseLimitChecker(Limit limit) {
        this.limit = limit;
    }

    /**
     * Method to process a parameter update. The method is expected called as part of a camel
     * route. The method will set the local parameter value, then process the limit check and
     * possibly issue a state parameter instance.
     *
     * @param arg0 A camel exchange carrying a parameter instance.
     * @throws Exception
     */
    public State processParameter(@Body Parameter newParameter) {
        logger.info("Limit state '{}' received parameter value for validation.", limit.getName());
        State state = doProcess(newParameter);
        lastValue = newParameter;
        return state;
    }

    /**
     * Method for receiving a notification of a limit update. The method is expected called as part of a camel
     * route. The method will set the local limit value, then process the limit check and
     * possibly issue a state parameter instance.
     *
     * @param arg0 A camel exchange carrying a Double instance expressing the size of the limit.
     * @throws Exception
     */
    public State processLimit(@Body Parameter newLimit) {
        limit.setValue(newLimit.getValue());
        logger.info("Limit '{}' set to '{}'.", limit.getName(), limit.getValue());
        return doProcess(lastValue);
    }

    /**
     * Method for receiving a notification of a enable / disable switch. The method is expected called as part of a
     * camel
     * route. The method will set the local enabled flag, then process the limit check and
     * possibly issue a state parameter instance.
     *
     * @param arg0 A camel exchange carrying a Boolean instance switching the limit on or off.
     * @throws Exception
     */
    public State processEnabled(@Body State newEnabled) throws Exception {
        limit.setEnabled(newEnabled.getValue());
        logger.info("Limit '{}' switches to ENABLED state '{}'.", limit.getName(), limit.getEnabled());
        return doProcess(lastValue);
    }

    /**
     * The actual method for processing the limit check. The limit will only be checked if the
     * limit is 'ready' and 'enabled';
     *
     * A limit is 'ready' if the limit is not null AND the parameter is not null.
     *
     * A limit is 'enabled' if the enabled flag is null OR the flag is equal to true.
     *
     * @param exchange A camel exchange carrying a Boolean instance switching the limit on or off.
     * @throws NotComparableTypeException
     */
    protected State doProcess(Parameter parameter) {
        State state = null;

        if (isEnabled() == true && isReady()) {
            state = new State(parameter.getID() + "/" + limit.getID(), limit.getStateName());
            state.setDescription(limit.getDescription());
            state.setApplicableTo(parameter.getID());
            state.setValue(checkLimit(parameter));
            state.setIssuedBy(limit.getID());
        }

        return state;
    }

    /**
     * Method to determine whether this limit is 'enabled'. The limit will be
     * enabled if;
     * 1) The parameter determining whether it is enabled is 'null', i.e. not set. OR
     * 2) The parameter determining whether it is enabled has the value 'true'.
     *
     * @return Flag that will be true of the limit is enabled. Else false.
     */
    protected boolean isEnabled() {
        return limit.getEnabled() == null || limit.getEnabled() == true;
    }

    /**
     * Method to determine whether this limit is 'ready'. The limit will be ready if;
     * 1) The limit is not null. AND
     * 2) The parameter value is not null.
     *
     * @return Flag indicating whether the limit can be considered ready.
     */
    protected boolean isReady() {
        return limit != null;
    }

    public Limit getLimit() {
        return limit;
    }

    public void setLimit(Limit limit) {
        this.limit = limit;
    }

    /**
     * Method actually performing the limit check, for example larger / smaller than.
     *
     * Before calling the method the user must ensure that the parameter and the limit are
     * not null. This should be done using the 'isReady()' method.
     *
     * @return boolean which is true if the parameter is within the limit, else false.
     * @throws NotComparableTypeException
     */
    protected abstract boolean checkLimit(Parameter parameter);
}


text:
package com.intuit.ipp.data;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
 * Wrapper class for the webhooks payload
 *
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class WebhooksEvent {

	List<EventNotification> eventNotifications;

	public List<EventNotification> getEventNotifications() {
		return eventNotifications;
	}

	public void setEventNotifications(List<EventNotification> eventNotifications) {
		this.eventNotifications = eventNotifications;
	}

}

redpajama_set_name: RedPajamaGithub


text:
<?php declare(strict_types=1);

namespace PhpParser\Builder;

use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Attribute;
use PhpParser\Node\AttributeGroup;
use PhpParser\Node\Expr;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar;
use PhpParser\Node\Scalar\LNumber;

class ParamTest extends \PHPUnit\Framework\TestCase
{
    public function createParamBuilder($name) {
        return new Param($name);
    }

    /**
     * @dataProvider provideTestDefaultValues
     */
    public function testDefaultValues($value, $expectedValueNode) {
        $node = $this->createParamBuilder('test')
            ->setDefault($value)
            ->getNode()
        ;

        $this->assertEquals($expectedValueNode, $node->default);
    }

    public function provideTestDefaultValues() {
        return [
            [
                null,
                new Expr\ConstFetch(new Node\Name('null'))
            ],
            [
                true,
                new Expr\ConstFetch(new Node\Name('true'))
            ],
            [
                false,
                new Expr\ConstFetch(new Node\Name('false'))
            ],
            [
                31415,
                new Scalar\LNumber(31415)
            ],
            [
                3.1415,
                new Scalar\DNumber(3.1415)
            ],
            [
                'Hallo World',
                new Scalar\String_('Hallo World')
            ],
            [
                [1, 2, 3],
                new Expr\Array_([
                    new Expr\ArrayItem(new Scalar\LNumber(1)),
                    new Expr\ArrayItem(new Scalar\LNumber(2)),
                    new Expr\ArrayItem(new Scalar\LNumber(3)),
                ])
            ],
            [
                ['foo' => 'bar', 'bar' => 'foo'],
                new Expr\Array_([
                    new Expr\ArrayItem(
                        new Scalar\String_('bar'),
                        new Scalar\String_('foo')
                    ),
                    new Expr\ArrayItem(
                        new Scalar\String_('foo'),
                        new Scalar\String_('bar')
                    ),
                ])
            ],
            [
                new Scalar\MagicConst\Dir,
                new Scalar\MagicConst\Dir
            ]
        ];
    }

    /**
     * @dataProvider provideTestTypes
     * @dataProvider provideTestNullableTypes
     * @dataProvider provideTestUnionTypes
     */
    public function testTypes($typeHint, $expectedType) {
        $node = $this->createParamBuilder('test')
            ->setTypeHint($typeHint)
            ->getNode()
        ;
        $type = $node->type;

        /* Manually implement comparison to avoid __toString stupidity */
        if ($expectedType instanceof Node\NullableType) {
            $this->assertInstanceOf(get_class($expectedType), $type);
            $expectedType = $expectedType->type;
            $type = $type->type;
        }

        $this->assertInstanceOf(get_class($expectedType), $type);
        $this->assertEquals($expectedType, $type);
    }

    public function provideTestTypes() {
        return [
            ['array', new Node\Identifier('array')],
            ['callable', new Node\Identifier('callable')],
            ['bool', new Node\Identifier('bool')],
            ['int', new Node\Identifier('int')],
            ['float', new Node\Identifier('float')],
            ['string', new Node\Identifier('string')],
            ['iterable', new Node\Identifier('iterable')],
            ['object', new Node\Identifier('object')],
            ['Array', new Node\Identifier('array')],
            ['CALLABLE', new Node\Identifier('callable')],
            ['mixed', new Node\Identifier('mixed')],
            ['Some\Class', new Node\Name('Some\Class')],
            ['\Foo', new Node\Name\FullyQualified('Foo')],
            ['self', new Node\Name('self')],
            [new Node\Name('Some\Class'), new Node\Name('Some\Class')],
        ];
    }

    public function provideTestNullableTypes() {
        return [
            ['?array', new Node\NullableType(new Node\Identifier('array'))],
            ['?Some\Class', new Node\NullableType(new Node\Name('Some\Class'))],
            [
                new Node\NullableType(new Node\Identifier('int')),
                new Node\NullableType(new Node\Identifier('int'))
            ],
            [
                new Node\NullableType(new Node\Name('Some\Class')),
                new Node\NullableType(new Node\Name('Some\Class'))
            ],
        ];
    }

    public function provideTestUnionTypes() {
        return [
            [
                new Node\UnionType([
                    new Node\Name('Some\Class'),
                    new Node\Identifier('array'),
                ]),
                new Node\UnionType([
                    new Node\Name('Some\Class'),
                    new Node\Identifier('array'),
                ]),
            ],
            [
                new Node\UnionType([
                    new Node\Identifier('self'),
                    new Node\Identifier('array'),
                    new Node\Name\FullyQualified('Foo')
                ]),
                new Node\UnionType([
                    new Node\Identifier('self'),
                    new Node\Identifier('array'),
                    new Node\Name\FullyQualified('Foo')
                ]),
            ],
        ];
    }

    public function testVoidTypeError() {
        $this->expectException(\LogicException::class);
        $this->expectExceptionMessage('Parameter type cannot be void');
        $this->createParamBuilder('test')->setType('void');
    }

    public function testInvalidTypeError() {
        $this->expectException(\LogicException::class);
        $this->expectExceptionMessage('Type must be a string, or an instance of Name, Identifier or ComplexType');
        $this->createParamBuilder('test')->setType(new \stdClass);
    }

    public function testByRef() {
        $node = $this->createParamBuilder('test')
            ->makeByRef()
            ->getNode()
        ;

        $this->assertEquals(
            new Node\Param(new Expr\Variable('test'), null, null, true),
            $node
        );
    }

    public function testVariadic() {
        $node = $this->createParamBuilder('test')
            ->makeVariadic()
            ->getNode()
        ;

        $this->assertEquals(
            new Node\Param(new Expr\Variable('test'), null, null, false, true),
            $node
        );
    }

    public function testAddAttribute() {
        $attribute = new Attribute(
            new Name('Attr'),
            [new Arg(new LNumber(1), false, false, [], new Identifier('name'))]
        );
        $attributeGroup = new AttributeGroup([$attribute]);

        $node = $this->createParamBuilder('attributeGroup')
            ->addAttribute($attributeGroup)
            ->getNode();

        $this->assertEquals(
            new Node\Param(new Expr\Variable('attributeGroup'), null, null, false, false, [], 0, [$attributeGroup]),
            $node
        );
    }
}


text:
package ru.stqa.pft.addressbook.model1;

import com.google.gson.annotations.Expose;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import org.hibernate.annotations.Table;
import org.hibernate.annotations.Type;

import javax.persistence.*;
import java.io.File;
import java.util.HashSet;
import java.util.Set;

@XStreamAlias("contact")
@Entity
@javax.persistence.Table(name = "addressbook")

public class ContactData {

    @XStreamOmitField
    @Id
    @Column (name = "id")
    private int id = Integer.MAX_VALUE;

    @Expose
    @Column (name = "firstname")
    private String firstname;

    @Expose
    @Column (name = "lastname")
    private String lastname;

    @Expose
    @Type(type = "text")
    @Column (name = "mobile")
    private String mobile;

    @Expose
    @Column (name = "email")
    @Type(type = "text")
    private String email;

    //@Transient
    //@Expose
    //private String group;

    @Column (name = "home")
    @Type(type = "text")
    private String homePhone;

    @Column (name = "work")
    @Type(type = "text")
    private String workPhone;

    @Transient
    private String allPhones;

    @Column (name = "email2")
    @Type(type = "text")
    private String email2;

    @Column (name = "email3")
    @Type(type = "text")
    private String email3;

    @Transient
    private String allEmails;

    @Column (name = "address")
    @Type(type = "text")
    private String address;

    @Column (name = "photo")
    @Type(type = "text")
    private String photo;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable (name = "address_in_groups",
            joinColumns = @JoinColumn(name = "id"), inverseJoinColumns = @JoinColumn(name = "group_id"))
    private Set<GroupData> groups = new HashSet<GroupData>();

    public File getPhoto() {
        return new File (photo);
    }

    public ContactData withPhoto(File photo) {
        this.photo = photo.getPath();
        return this;
    }

    public String getEmail2() {
        return email2;
    }

    public ContactData withEmail2(String email2) {
        this.email2 = email2;
        return this;
    }

    public String getEmail3() {
        return email3;
    }

    public ContactData withEmail3(String email3) {
        this.email3 = email3;
        return this;
    }

    public String getAllEmails() {
        return allEmails;
    }

    public ContactData withAllEmails(String allEmails) {
        this.allEmails = allEmails;
        return this;
    }

    public String getAddress() {
        return address;
    }

    public ContactData withAddress(String address) {
        this.address = address;
        return this;
    }

    public ContactData withAllPhones(String allPhones) {
        this.allPhones = allPhones;
        return this;
    }

    public ContactData() {
    }

    public ContactData withHomePhone(String home) {
        this.homePhone = home;
        return this;
    }

    public ContactData withWorkPhone(String work) {
        this.workPhone = work;
        return this;
    }

    public ContactData withFirstname(String firstname) {
        this.firstname = firstname;
        return this;
    }

    public ContactData withLastname(String lastname) {
        this.lastname = lastname;
        return this;
    }

    public ContactData withMobile(String mobile) {
        this.mobile = mobile;
        return this;
    }

    public ContactData withEmail(String email) {
        this.email = email;
        return this;
    }

    //public ContactData withGroup(String group) {
        //this.group = group;
        //return this;
    //}

    public ContactData withId(int id) {
        this.id = id;
        return this;
    }

    public int getId() {
        return id;
    }

    public String getAllPhones() {
        return allPhones;
    }

    public String getFirstname() {
        return firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public String getHomePhone() {
        return homePhone;
    }

    public String getWorkPhone() {
        return workPhone;
    }

    public String getMobile() {
        return mobile;
    }

    public String getEmail() {
        return email;
    }

    //public String getGroup() {
        //return group;
    //}

    public Groups getGroups() {
        return new Groups(groups);
    }

    @Override
    public String toString() {
        return "ContactData{" +
                "id='" + id + '\'' +
                ", firstname='" + firstname + '\'' +
                ", lastname='" + lastname + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ContactData that = (ContactData) o;

        if (id != that.id) return false;
        if (firstname != null ? !firstname.equals(that.firstname) : that.firstname != null) return false;
        if (lastname != null ? !lastname.equals(that.lastname) : that.lastname != null) return false;
        if (mobile != null ? !mobile.equals(that.mobile) : that.mobile != null) return false;
        return email != null ? email.equals(that.email) : that.email == null;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + (firstname != null ? firstname.hashCode() : 0);
        result = 31 * result + (lastname != null ? lastname.hashCode() : 0);
        result = 31 * result + (mobile != null ? mobile.hashCode() : 0);
        result = 31 * result + (email != null ? email.hashCode() : 0);
        return result;
    }

    public ContactData inGroup(GroupData group) {
        groups.add(group);
        return this;
    }
}


text:
<?php

namespace Dotdigitalgroup\Email\Block\Adminhtml\Config\Accounts;

class IntegrationSetupProgress extends \Magento\Config\Block\System\Config\Form\Field
{
    /**
     * Prepare layout.
     *
     * @return $this|IntegrationSetupProgress
     */
    protected function _prepareLayout()
    {
        parent::_prepareLayout();
        $this->setTemplate('integration/setup.phtml');
        return $this;
    }

    /**
     * Get element html.
     *
     * @param \Magento\Framework\Data\Form\Element\AbstractElement $element
     * @return string
     */
    protected function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element)
    {
        return $this->toHtml();
    }

    /**
     * Removes use Default Checkbox.
     *
     * @param \Magento\Framework\Data\Form\Element\AbstractElement $element
     * @return string
     */
    public function render(\Magento\Framework\Data\Form\Element\AbstractElement $element)
    {
        $element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue();
        return parent::render($element);
    }
}


text:
var myApp = angular.module('myApp', [
  'ngCookies', 'auth0', 'ngRoute', 'angular-jwt', 'angular-storage'
]);

myApp.config(function ($routeProvider, authProvider, $httpProvider, jwtInterceptorProvider) {
  $routeProvider
  .when('/logout',  {
    templateUrl: 'views/logout.html',
    controller: 'LogoutCtrl'
  })
  .when('/login',   {
    templateUrl: 'views/login.html',
    controller: 'LoginCtrl',
  })
  .when('/', {
    templateUrl: 'views/root.html',
    controller: 'RootCtrl',
    /* isAuthenticated will prevent user access to forbidden routes */
    requiresLogin: true
  });

  authProvider.init({
    domain: 'samples.auth0.com',
    clientID: 'BUIJSW9x60sIHBw8Kd9EmCbj8eDIFxDC',
    loginUrl: '/login'
  });

  authProvider.on('loginSuccess', function($location, profilePromise, idToken, store) {
    console.log("Login Success");
    profilePromise.then(function(profile) {
      store.set('profile', profile);
      store.set('token', idToken);
    });
    $location.path('/');
  });

  authProvider.on('authenticated', function($location) {
    console.log("Authenticated");

  });

  authProvider.on('logout', function() {
    console.log("Logged out");
  })

  // Add a simple interceptor that will fetch all requests and add the jwt token to its authorization header.
  // NOTE: in case you are calling APIs which expect a token signed with a different secret, you might
  // want to check the delegation-token example

  jwtInterceptorProvider.tokenGetter = function(store) {
    return store.get('token');
  }

  // Add a simple interceptor that will fetch all requests and add the jwt token to its authorization header.
  // NOTE: in case you are calling APIs which expect a token signed with a different secret, you might
  // want to check the delegation-token example
  $httpProvider.interceptors.push('jwtInterceptor');
}).run(function($rootScope, auth, store, jwtHelper, $location) {
  $rootScope.$on('$locationChangeStart', function() {
    if (!auth.isAuthenticated) {
      var token = store.get('token');
      if (token) {
        if (!jwtHelper.isTokenExpired(token)) {
          auth.authenticate(store.get('profile'), token);
        } else {
          $location.path('/login');
        }
      }
    }

  });
});


text:
package org.scaladebugger.api.lowlevel.monitors

import org.scalamock.scalatest.MockFactory
import org.scalatest.{FunSpec, Matchers, ParallelTestExecution}
import org.scaladebugger.api.lowlevel.DummyOperationException
import org.scaladebugger.test.helpers.ParallelMockFunSpec

class DummyMonitorContendedEnterManagerSpec extends ParallelMockFunSpec
{
  private val TestRequestId = java.util.UUID.randomUUID().toString
  private val monitorContendedEnterManager = new DummyMonitorContendedEnterManager

  describe("DummyMonitorContendedEnterManager") {
    describe("#monitorContendedEnterRequestList") {
      it("should return an empty list") {
        monitorContendedEnterManager.monitorContendedEnterRequestList should be (empty)
      }
    }

    describe("#createMonitorContendedEnterRequestWithId") {
      it("should return a failure of dummy operation") {
        val result = monitorContendedEnterManager.createMonitorContendedEnterRequestWithId(
          TestRequestId
        )

        result.isFailure should be (true)
        result.failed.get shouldBe a [DummyOperationException]
      }
    }

    describe("#hasMonitorContendedEnterRequest") {
      it("should return false") {
        val expected = false

        val actual = monitorContendedEnterManager.hasMonitorContendedEnterRequest(
          TestRequestId
        )

        actual should be (expected)
      }
    }

    describe("#getMonitorContendedEnterRequest") {
      it("should return None") {
        val expected = None

        val actual = monitorContendedEnterManager.getMonitorContendedEnterRequest(
          TestRequestId
        )

        actual should be (expected)
      }
    }

    describe("#getMonitorContendedEnterRequestInfo") {
      it("should return None") {
        val expected = None

        val actual = monitorContendedEnterManager.getMonitorContendedEnterRequestInfo(
          TestRequestId
        )

        actual should be (expected)
      }
    }

    describe("#removeMonitorContendedEnterRequest") {
      it("should return false") {
        val expected = false

        val actual = monitorContendedEnterManager.removeMonitorContendedEnterRequest(
          TestRequestId
        )

        actual should be (expected)
      }
    }
  }
}


text:
<?php
#**************************************************************************
#  openSIS is a free student information system for public and non-public
#  schools from Open Solutions for Education, Inc. web: www.os4ed.com
#
#  openSIS is  web-based, open source, and comes packed with features that
#  include student demographic info, scheduling, grade book, attendance,
#  report cards, eligibility, transcripts, parent portal,
#  student portal and more.
#
#  Visit the openSIS web site at http://www.opensis.com to learn more.
#  If you have question regarding this system or the license, please send
#  an email to info@os4ed.com.
#
#  This program is released under the terms of the GNU General Public License as
#  published by the Free Software Foundation, version 2 of the License.
#  See 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 General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************************
include('../../Redirect_modules.php');
DrawBC("Users >> ".ProgramTitle());

include 'Menu.php';

if(is_numeric(clean_param($_REQUEST['profile_id'],PARAM_INT)))
{
	$exceptions_RET = DBGet(DBQuery('SELECT PROFILE_ID,MODNAME,CAN_USE,CAN_EDIT FROM profile_exceptions WHERE PROFILE_ID=\''.$_REQUEST[profile_id].'\''),array(),array('MODNAME'));
	$profile_RET = DBGet(DBQuery('SELECT PROFILE FROM user_profiles WHERE ID=\''.$_REQUEST[profile_id].'\''));
	$xprofile = $profile_RET[1]['PROFILE'];
	if($xprofile=='student')
	{
		$xprofile = 'parent';
		unset($menu['Users']);
	}
}

if(clean_param($_REQUEST['modfunc'],PARAM_ALPHAMOD)=='delete' && AllowEdit())
{
	$profile_RET = DBGet(DBQuery('SELECT TITLE FROM user_profiles WHERE ID=\''.$_REQUEST[profile_id].'\''));

	if(Prompt('Confirm Delete','Are you sure you want to delete the user profile '.$profile_RET[1]['TITLE'].'?','Users of that profile will retain their permissions as a custom set which can be modified on a per-user basis through the User Permissions program.'))
	{
		DBQuery('DELETE FROM user_profiles WHERE ID=\''.$_REQUEST['profile_id'].'\'');
		DBQuery('DELETE FROM staff_exceptions WHERE USER_ID IN (SELECT STAFF_ID FROM staff WHERE PROFILE_ID=\''.$_REQUEST['profile_id'].'\')');
		DBQuery('INSERT INTO staff_exceptions (USER_ID,MODNAME,CAN_USE,CAN_EDIT) SELECT s.STAFF_ID,e.MODNAME,e.CAN_USE,e.CAN_EDIT FROM staff s,profile_exceptions e WHERE s.PROFILE_ID=\''.$_REQUEST[profile_id].'\' AND s.PROFILE_ID=e.PROFILE_ID');
		DBQuery('DELETE FROM profile_exceptions WHERE PROFILE_ID=\''.$_REQUEST['profile_id'].'\'');
		unset($_REQUEST['modfunc']);
		unset($_REQUEST['profile_id']);
	}
}

if(clean_param($_REQUEST['modfunc'],PARAM_ALPHAMOD)=='update' && AllowEdit() && !$_REQUEST['new_profile_title'])
{
	$tmp_menu = $menuprof;
	$categories_RET = DBGet(DBQuery('SELECT ID,TITLE FROM student_field_categories'));
	foreach($categories_RET as $category)
	{
		$file = 'Students/Student.php&category_id='.$category['ID'];
		$tmp_menu['Students'][$xprofile][$file] = '     › '.$category['TITLE'];
	}
	$categories_RET = DBGet(DBQuery('SELECT ID,TITLE FROM staff_field_categories'));
	foreach($categories_RET as $category)
	{
		$file = 'Users/User.php&category_id='.$category['ID'];
		$tmp_menu['Users'][$xprofile][$file] = '     › '.$category['TITLE'];
	}

	foreach($tmp_menu as $modcat=>$profiles)
	{
		$values = $profiles[$xprofile];
		foreach($values as $modname=>$title)
		{
			if(!is_numeric($modname))
			{
				if(!count($exceptions_RET[$modname]) && ($_REQUEST['can_edit'][str_replace('.','_',$modname)] || $_REQUEST['can_use'][str_replace('.','_',$modname)]))
					DBQuery('INSERT INTO profile_exceptions (PROFILE_ID,MODNAME) values(\''.$_REQUEST[profile_id].'\',\''.$modname.'\')');
				elseif(count($exceptions_RET[$modname]) && !$_REQUEST['can_edit'][str_replace('.','_',$modname)] && !$_REQUEST['can_use'][str_replace('.','_',$modname)])
					DBQuery('DELETE FROM profile_exceptions WHERE PROFILE_ID=\''.$_REQUEST[profile_id].'\' AND MODNAME=\''.$modname.'\'');

				if($_REQUEST['can_edit'][str_replace('.','_',$modname)] || $_REQUEST['can_use'][str_replace('.','_',$modname)])
				{
					$update = 'UPDATE profile_exceptions SET ';
					if($_REQUEST['can_edit'][str_replace('.','_',$modname)])
						$update .= 'CAN_EDIT=\''.'Y'.'\',';
					else
						$update .= 'CAN_EDIT=NULL,';
					if($_REQUEST['can_use'][str_replace('.','_',$modname)])
						$update .= 'CAN_USE=\''.'Y'.'\'';
					else
						$update .= 'CAN_USE=NULL';
					$update .= ' WHERE PROFILE_ID=\''.$_REQUEST[profile_id].'\' AND MODNAME=\''.$modname.'\';';
					DBQuery($update);
				}
			}
		}
	}
	$exceptions_RET = DBGet(DBQuery('SELECT MODNAME,CAN_USE,CAN_EDIT FROM profile_exceptions WHERE PROFILE_ID=\''.$_REQUEST[profile_id].'\''),array(),array('MODNAME'));
	unset($tmp_menu);
	unset($_REQUEST['modfunc']);
	unset($_REQUEST['can_edit']);
	unset($_REQUEST['can_use']);
}

if(clean_param($_REQUEST['new_profile_title'],PARAM_NOTAGS) && AllowEdit())
{
	// $id = DBGet(DBQuery("SELECT ".db_seq_nextval('USER_PROFILES_SEQ')." AS ID".FROM_DUAL));
        $id = DBGet(DBQuery('SHOW TABLE STATUS LIKE \''.'user_profiles'.'\''));
        $id[1]['ID']= $id[1]['AUTO_INCREMENT'];
	$id = $id[1]['ID'];
	$exceptions_RET = array();
	DBQuery('INSERT INTO user_profiles (TITLE,PROFILE) values(\''.clean_param($_REQUEST['new_profile_title'],PARAM_NOTAGS).'\',\''.clean_param($_REQUEST['new_profile_type'],PARAM_ALPHA).'\')');
	$_REQUEST['profile_id'] = $id;
	$xprofile = $_REQUEST['new_profile_type'];
	unset($_REQUEST['new_profile_title']);
	unset($_REQUEST['new_profile_type']);
	unset($_SESSION['_REQUEST_vars']['new_profile_title']);
	unset($_SESSION['_REQUEST_vars']['new_profile_type']);
}

if($_REQUEST['modfunc']!='delete')
{
PopTable('header','Permissions');
	echo "<FORM name=pref_form id=pref_form action=Modules.php?modname=$_REQUEST[modname]&modfunc=update&profile_id=$_REQUEST[profile_id] method=POST>";
	DrawHeaderHome('Select the programs that users of this profile can use and which programs those users can use to save information.');
	echo '
';
	echo '

';
	echo '
';
	$style = ' style="border:1px; border-style: none none none none; padding:4px;"';
	$style1 = ' style="border:1px; border-style: solid none none none;"';
	//$profiles_RET = DBGet(DBQuery("SELECT ID,TITLE,PROFILE FROM user_profiles"));
	$profiles_RET = DBGet(DBQuery('SELECT ID,TITLE,PROFILE FROM user_profiles ORDER BY ID'),array(),array('PROFILE','ID'));
	echo '
Profiles
';
	foreach(array('admin','teacher','parent','student') as $profiles)
	{
	foreach($profiles_RET[$profiles] as $id=>$profile)
	{
		if($_REQUEST['profile_id']!='' && $id==$_REQUEST['profile_id'])
			echo '
'.(AllowEdit()&&$id>3?button('remove','',"Modules.php?modname=$_REQUEST[modname]&modfunc=delete&profile_id=$id",20):'').'	';
		else
			echo '
'.(AllowEdit()&&$id>3?button('remove','',"Modules.php?modname=$_REQUEST[modname]&modfunc=delete&profile_id=$id",15):'').'	';
		echo ''.($id>3?'':'').$profile[1]['TITLE'].($id>3?'':'').'  ';
		echo '	';
		echo '	';
		echo '
';
	}
	}
	if($_REQUEST['profile_id']=='')
		echo '

';

	if(AllowEdit())
	{
	echo '
';
	echo '<a style="cursor: pointer;" onclick=\'document.getElementById("selected_tr").onmouseover="this.style.backgroundColor=\"'.Preferences('HIGHLIGHT').'\"; this.style.color=\"white\";"; document.getElementById("selected_tr").onmouseout="this.style.cssText=\"background-color:transparent; color:black;\";"; document.getElementById("selected_tr").style.cssText="background-color:transparent; color:black;"; changeHTML({"new_id_div":"new_id_content"},["main_div"]);document.getElementById("new_tr").onmouseover="";document.getElementById("new_tr").onmouseout="";this.onclick="";\'> Add a User Profile

 ';
	echo '	';
	//echo ' 	';
	#echo "	";
	echo '
';
	}

	echo '
';
	echo '		';
	echo '
';
	if($_REQUEST['profile_id']!='')
	{
		#PopTable('header','Permissions');
		echo '
';
		echo '
Permissions
';
		foreach($menuprof as $modcat=>$profiles)
		{
			$values = $profiles[$xprofile];

			echo '
';
			echo "".str_replace('_',' ',$modcat)."	 	";
			echo "Can Use".(AllowEdit()?"<INPUT type=checkbox name=can_use_$modcat onclick='checkAll(this.form,this.form.can_use_$modcat.checked,\"can_use[$modcat\");'>":'')."	";
			if($xprofile=='admin' || $modcat=='Students')
				echo"  Can Edit".(AllowEdit()?"<INPUT type=checkbox name=can_edit_$modcat onclick='checkAll(this.form,this.form.can_edit_$modcat.checked,\"can_edit[$modcat\");'>":'')."	";
			else
				echo"	";
			echo "
";
			if(count($values))
			{
				foreach($values as $file=>$title)
				{
					if(!is_numeric($file))
					{
						$can_use = $exceptions_RET[$file][1]['CAN_USE'];
						$can_edit = $exceptions_RET[$file][1]['CAN_EDIT'];

						echo "
		";

						echo "<INPUT type=checkbox name=can_use[".str_replace('.','_',$file)."] value=true".($can_use=='Y'?' CHECKED':'').(AllowEdit()?'':' DISABLED').">	";
						if($xprofile=='admin')
                            echo "<INPUT type=checkbox name=can_edit[".str_replace('.','_',$file)."] value=true".($can_edit=='Y'?' CHECKED':'').(AllowEdit()?'':' DISABLED').">	";
						elseif($xprofile=='parent' && $file=='Scheduling/Requests.php')
                            echo "<INPUT type=checkbox name=can_edit[".str_replace('.','_',$file)."] value=true".($can_edit=='Y'?' CHECKED':'').(AllowEdit()?'':' DISABLED').">	";
                        else
                            echo "	";
						echo "    $title

";

						if($modcat=='Students' && $file=='Students/Student.php')
						{
							$categories_RET = DBGet(DBQuery('SELECT ID,TITLE FROM student_field_categories ORDER BY SORT_ORDER,TITLE'));
							foreach($categories_RET as $category)
							{
								$file = 'Students/Student.php&category_id='.$category['ID'];
								$title = '     › '.$category['TITLE'];
								$can_use = $exceptions_RET[$file][1]['CAN_USE'];
								$can_edit = $exceptions_RET[$file][1]['CAN_EDIT'];

								echo "
		";
								echo "<INPUT type=checkbox name=can_use[".str_replace('.','_',$file)."] value=true".($can_use=='Y'?' CHECKED':'').(AllowEdit()?'':' DISABLED').">	";
								echo "<INPUT type=checkbox name=can_edit[".str_replace('.','_',$file)."] value=true".($can_edit=='Y'?' CHECKED':'').(AllowEdit()?'':' DISABLED').">	";
								echo "$title

";
							}
						}
						elseif($modcat=='Users' && $file=='Users/User.php')
						{
							$categories_RET = DBGet(DBQuery('SELECT ID,TITLE FROM staff_field_categories ORDER BY SORT_ORDER,TITLE'));
							foreach($categories_RET as $category)
							{
								$file = 'Users/User.php&category_id='.$category['ID'];
								$title = '     › '.$category['TITLE'];
								$can_use = $exceptions_RET[$file][1]['CAN_USE'];
								$can_edit = $exceptions_RET[$file][1]['CAN_EDIT'];

								echo "
		";
								echo "<INPUT type=checkbox name=can_use[".str_replace('.','_',$file)."] value=true".($can_use=='Y'?' CHECKED':'').(AllowEdit()?'':' DISABLED').">	";
								echo "<INPUT type=checkbox name=can_edit[".str_replace('.','_',$file)."] value=true".($can_edit=='Y'?' CHECKED':'').(AllowEdit()?'':' DISABLED').">	";
								echo "    $title

";
							}
						}
					}
					else
						echo '
		 '.$title.'
';

				}
			}
			echo '

';
		}
		echo '
';
		#PopTable('footer');
	//	echo ''.SubmitButton('Save', '', 'class=btn_medium onclick=\'formload_ajax("pref_form");\'').'';
		echo ''.SubmitButton('Save', '', 'class=btn_medium').'';
		// pref_form
	}
	echo '
';
	echo '

';
	echo '</FORM>';
	PopTable('footer');
	echo '
<fieldset><legend>Add a User Profile</legend>

Title 	<INPUT type=text name=new_profile_title>
';
	echo '
Type 	<SELECT name=new_profile_type><OPTION value=admin>Administrator<OPTION value=teacher>Teacher<OPTION value=parent>Parent</SELECT>

<input type=submit value=save class=btn_medium>

</fieldset>
';
}
?>


text:
class LinkedAccount::Github < LinkedAccount::Base

  has_many :issue_ranks, foreign_key: :linked_account_id, class_name: 'IssueRank::LinkedAccountGithub'

  has_one :team, foreign_key: :linked_account_id

  validates :uid, uniqueness: true, on: :create

  class GithubAccountLinkError < Exception ; end

  def self.oauth_url(options={})
    %(https://github.com/login/oauth/authorize?#{{
      client_id:  Api::Application.config.github_api[:client_id],
      scope:      options[:scope],
      # scope:      ((options[:scope]||'').split(',') + ['user:email','read:org']).join(','),
      state:      options[:state]
    }.reject { |k,v| v.nil? }.to_param})
  end

  def self.find_or_create_via_oauth_code(code)
    # hit github oauth server to exchange code for access_token
    oauth_response = ::Github::API.call(
      url: "/login/oauth/access_token",
      type: 'POST',
      host: "https://github.com", # manually override api.github.com
      params: {
        client_id:      Api::Application.config.github_api[:client_id],
        client_secret:  Api::Application.config.github_api[:client_secret],
        code:           code # provided from :login step. this is exchanged for an oauth token
      },
      headers: { 'Accept' => 'application/json' }
    )

    # if we got an error, raise!
    raise ::Github::API::Error, oauth_response.data[:error] unless oauth_response.success?

    # get user object from Github with oauth_token (full_response so we can pull out .scope)
    github_user_response = ::Github::API.call(
      url: '/user',
      params: { access_token: oauth_response.data[:access_token] }
    )
    github_user_data = github_user_response.data

    # TODO figure out what causes this instead of raising.
    unless github_user_response.success? && github_user_data.has_key?("login") && github_user_data.has_key?("id")
      raise GithubAccountLinkError, "Oh no! Something went wrong linking this github account! GO FIX IT"
    end

    # find/update of create a linked_account model
    linked_account = update_attributes_from_github_data(github_user_data)

    # update with oauth token and permissions
    linked_account.update_attributes(oauth_token: oauth_response.data[:access_token], permissions: github_user_response.scopes.join(","))

    # asynchronously find projects (since it's oauth, this is always a User, never a Organization)
    linked_account.sync_all_data_if_necessary

    linked_account
  end

  def self.find_by_access_token(access_token)
    github_account_id, time, hash = (access_token||'').split('.')
    return nil if github_account_id.blank? || time.blank? || hash.blank?
    return nil unless time.to_i > Time.now.to_i
    return nil unless (github_account = LinkedAccount::Github::User.find_by_id(github_account_id))
    return nil unless hash == self.hash_access_token(github_account, time)
    github_account
  end

  def create_access_token
    time = 1.day.from_now.to_i
    "#{self.id}.#{time}.#{self.class.hash_access_token(self, time)}"
  end

  def api(options={})
    options[:params] ||= {}
    options[:params].merge!(access_token: oauth_token) if !options[:params][:access_token] && oauth_token?
    ::Github::API.call(options)
  rescue ::Github::API::Unauthorized
    if oauth_token
      update_attributes!(oauth_token: nil)
      retry
    else
      raise
    end
  end

  # get remote user info from GitHub
  def remote_info
    return nil unless oauth_token?
    response = api(url: '/user')
    response.data
  end

  def remote_sync(options={})
    unless deleted_at
      github_data = api(url: self.github_api_path).data
      self.class.update_attributes_from_github_data(github_data, obj: self)
    end
  rescue ::Github::API::NotFound
    deleted_at = Time.now
    update_attributes!(deleted_at: deleted_at)
  end

  # array of logins for users that this account is following
  def following_logins
    return [] if oauth_token.blank?

    response = api(url: "/users/#{login}/following")

    if response.success?
      response.data.map { |d| d["login"] }
    else
      update_attributes(oauth_token: nil) and []
    end
  end

  def github_api_path
    "/user/#{remote_id}"
  end

  #def sync_permissions
  #  return [] unless oauth_token?
  #  response = api(url: '/', type: 'HEAD')
  #  response.scopes
  #end

  def has_permission?(permission)
    permissions.include? permission.to_s
  end

  # can this account modify the repository?
  def can_modify_repository?(tracker)
    response = api(url: "/repos/#{tracker.full_name}/collaborators/#{login}/permission")
    json = JSON.parse(response.body).with_indifferent_access
    if ['admin', 'write'].include?(json[:permission])
      return true
    end
    false
  rescue Github::API::Unauthorized
    false
  rescue Github::API::NotFound
    false
  end

  def fetch_events
    urls = (1..10).map do |i|
      path = case self
      when LinkedAccount::Github::User then "/users/#{login}/events"
      when LinkedAccount::Github::Organization then "/orgs/#{login}/events"
      end

      uri = URI.parse("https://api.github.com#{path}")
      uri.query = Api::Application.config.github_api.merge(page: i, per_page: 30).to_param
      uri.to_s
    end

    events = []
    EM.run {
      EM::Iterator.new(urls, 40).each(
        proc { |url, iterator|
          http = EventMachine::HttpRequest.new(url).get
          http.callback { |http|
            events += JSON.parse(http.response)
            iterator.next
          }
        },
        proc { EM.stop }
      )
    }
    events
  end

  # increment IssueRank::LinkedAccountGithub for Team and Issue from GitHub user events.
  def sync_issue_ranks
    # Find or create rank from events, add value based on event
    IssueRank::LinkedAccountGithub.increment_rank_from_events(self, fetch_events)
  end

  def self.update_attributes_from_github_array(github_data)
    # bulk load all users
    rails_please_autoload = [LinkedAccount::Github::User, LinkedAccount::Github::Organization]
    user_hash = LinkedAccount::Github.where("uid in (?)", github_data.map { |user_data| user_data['id'] })
    user_hash = user_hash.inject({}) { |hash,obj| hash[obj.uid.to_i] = obj unless hash[obj.uid.to_i] && hash[obj.uid.to_i].id < obj.id; hash }

    github_data.map do |user_data|
      update_attributes_from_github_data(user_data, obj: (user_hash[user_data['id'].to_i] || LinkedAccount::Github.new()))
    end
  end

  def remote_id
    uid
  end

  def self.update_attributes_from_github_data(github_data, options={})
    return nil if github_data.blank? || github_data['url'] == "https://api.github.com/users/"
    raise "NO ID #{github_data.inspect}" unless remote_id = github_data['id']
    # Find object
    rails_please_autoload = [LinkedAccount::Github::User, LinkedAccount::Github::Organization]
    obj = options[:obj] || LinkedAccount::Github.where("uid = ?", remote_id)[0] || LinkedAccount::Github.new()

    obj.uid = remote_id
    obj.login = github_data['login'] if github_data.has_key?('login')
    obj.email = github_data['email'] if github_data.has_key?('email')
    obj.first_name = github_data['name'] if github_data.has_key?('name')
    obj.image_url = get_cloudinary_id_from_github_data(github_data)
    obj.company = github_data['company'] if github_data.has_key?('company')
    obj.location = github_data['location'] if github_data.has_key?('location')
    obj.bio = github_data['bio'] if github_data.has_key?('bio')
    obj.followers = github_data['followers'] if github_data.has_key?('followers')
    obj.following = github_data['following'] if github_data.has_key?('following')

    # sanitize email address
    unless obj.email.nil?
      # doesn't have an @ sign, can't be real
      obj.email = nil if !obj.email.try(:[], '@')

      # no github employees
      obj.email = nil if obj.email.try(:[], '@github.com')
      obj.email = nil if github_data['site_admin']
      obj.email = nil if github_data['company'].try(:match, /github/i)
    end

    # Update single-table-inheritance type
    # TODO not sure if URL is a good fallback to type, but it's probably fine 90% of the time.
    if github_data['type'] == 'Organization'
      obj.type = 'LinkedAccount::Github::Organization'
    elsif github_data['type'] == 'User'
      obj.type = 'LinkedAccount::Github::User'
    elsif github_data['type'] == 'Bot'
      obj.type = 'LinkedAccount::Github::Bot'
    else
      raise "Type not determined: #{github_data.inspect}"
    end

    type_was_changed = obj.type_changed?

    # Save if it changed
    obj.save! if obj.changed?

    type_was_changed ? obj.type.constantize.find_by(id: obj.id) : obj
  rescue ActiveRecord::RecordInvalid, PG::UniqueViolation, ActiveRecord::RecordNotUnique
    if options[:try_again]
      raise
    else
      # sometimes we can just try again......
      update_attributes_from_github_data(github_data, options.merge(try_again: true, obj: nil))
    end
  end

  # this and merge_and_destroy really shouldn't be necessary if things are working correctly............
  def self.find_and_merge_duplicates!(uids=nil)
    rails_please_autoload = [LinkedAccount::Github::User, LinkedAccount::Github::Organization]

    query = LinkedAccount::Github.group(:uid).having('count(*) > 1')
    query = query.where(uid: uids) if uids
    query.pluck(:uid).compact.each do |uid|
      accounts = LinkedAccount::Github.where(uid: uid).to_a

      good_account = accounts.find { |a| a.oauth_token }   #linked account
      good_account ||= accounts.find { |a| a.person_id }   #linked account
      good_account ||= accounts.sort_by(&:id).first        #first created
      bad_accounts = accounts - [good_account]

      LinkedAccount::Github.merge_and_destroy!(good_account.id, bad_accounts.map(&:id))

    end
  end

  #reload!; LinkedAccount::Github::User.merge_and_destroy!(LinkedAccount::Github::User.find(1092384), LinkedAccount::Github::User.find(1092383))
  def self.merge_and_destroy!(good_account_id, *bad_account_ids)
    bad_account_ids.flatten!
    bad_account_ids = bad_account_ids - [good_account_id]
    raise "no bad ids" if bad_account_ids.empty?

    good_account = LinkedAccount::Github.where(id: good_account_id).first
    bad_accounts = LinkedAccount::Github.where(id: bad_account_ids)

    puts "MERGING #{good_account.uid}: #{good_account_id} <-- #{bad_account_ids.inspect}"

    puts "BEFORE COUNTS: "
    puts "Comment: %d" % Comment.where(author_linked_account_id: bad_account_ids).count
    puts "Issue: %d" % Issue.where(author_linked_account_id: bad_account_ids).count
    puts "Team: %d" % Team.where(linked_account_id: bad_account_ids).count
    puts "IssueRank: %d" % IssueRank.where(linked_account_id: bad_account_ids).count
    puts "TrackerRelation: %d" % TrackerRelation.where(linked_account_id: bad_account_ids).count

    puts "MERGING:"
    puts "Comment: %d" % Comment.where(author_linked_account_id: bad_account_ids).update_all(author_linked_account_id: good_account_id)
    puts "Issue: %d" % Issue.where(author_linked_account_id: bad_account_ids).update_all(author_linked_account_id: good_account_id)
    puts "TrackerRelation: %d" % TrackerRelation.where(linked_account_id: bad_account_ids).delete_all
    puts "Team: %d" % Team.where(linked_account_id: bad_account_ids).update_all(linked_account_id: good_account_id)

    puts "AFTER COUNTS: "
    puts "Comment: %d" % Comment.where(author_linked_account_id: bad_account_ids).count
    puts "Issue: %d" % Issue.where(author_linked_account_id: bad_account_ids).count
    puts "Team: %d" % Team.where(linked_account_id: bad_account_ids).count
    puts "IssueRank: %d" % IssueRank.where(linked_account_id: bad_account_ids).count
    puts "TrackerRelation: %d" % TrackerRelation.where(linked_account_id: bad_account_ids).count

    if (Team.where(linked_account_id: bad_account_ids).count + IssueRank.where(linked_account_id: bad_account_ids).count + TrackerRelation.where(linked_account_id: bad_account_ids).count) == 0
    puts "DELETED: " % LinkedAccount::Github.where(id: bad_account_ids).delete_all
    else
      puts "NOT OKAY TO DELETE, SKIPPING"
    end
  end

protected

  def self.get_cloudinary_id_from_github_data(github_data)
    if github_data.has_key?('gravatar_id') && github_data['gravatar_id'].present?
      "gravatar:#{github_data['gravatar_id']}"
    elsif github_data.has_key?('avatar_url') && github_data['avatar_url'].present?
      "#{github_data['avatar_url']}"
    end
  end

  def self.hash_access_token(person, time)
    Digest::SHA1.hexdigest("#{person.id}.#{time}.#{Api::Application.config.linked_account_secret}")
  end

end


text:
=begin      ::about::
author:     Kyle Yetter <kcy5b@yahoo.com>
created on: June 05, 2010
purpose:    (program | library | utility script | ?)
summary:
loads:      files required by this
autoloads:  autoload entries in this (e.g. YAML(yaml))
=end

module ANTLRDoc
class Article
  DEFAULT_SOURCE = "h1. Coming Soon".freeze

  attr_accessor :source_file, :name, :title, :time, :stylesheets, :scripts,
                :output_directory, :template

  def initialize( source_file, title = nil, guide = nil )
    @source_file = source_file
    @guide = guide

    if not test( ?f, @source_file ) and test( ?d, File.dirname( @source_file ) )
      warn( "article source #{ source_file } does not exist" )
      warn( "creating an empty source file at #{ source_file }" )
      open( @source_file, 'w' ) { | f | f.write( '' ) }
    end

    @name  = File.basename( @source_file, '.*' )
    @title = title || Inflection.title_case( @name )
    @template = @source =  nil
    @email = @author = nil
    @time = File.mtime( source_file )
    @stylesheets = []
    @scripts = []
    @inline_styles = []
  end

  def output_path( *args )
    dir = @guide ? @guide.output : '.'
    File.join( dir, *args )
  end

  %w( email author template ).each do | property |
    class_eval( <<-END, __FILE__, __LINE__ + 1 )
      attr_writer :#{ property }

      def #{ property }
        @#{ property } or @guide && @guide.#{ property }
      end
    END
  end

  def empty?
    not File.size?( @source_file )
  end

  def source
    @source ||= begin
      empty? ? DEFAULT_SOURCE.dup : File.read( @source_file )
    rescue => e
      warn( "could not read article source from `#@source_file':" )
      e.dump
      DEFAULT_SOURCE.dup
    end
  end

  def configure( template, options = {} )
    @template = template
    title = options[ :title ] and @title = title
    time  = options[ :time ]  and @time  = time
    author = options[ :author ] and @author = author
    email = options[ :email ] and @email = email
    return( self )
  end

  def convert( dest = output_file )
    open( dest, 'w' ) do | out |
      out.write( generate )
    end
  end

  def output_file
    File.join( @output_directory, "#@name.html" )
  end

  def generate
    outline
    @template.result( binding )
  end

  def body
    @body ||= begin
      rc = RedCloth.new( preprocess )
      rc.hard_breaks = false
      rc.to_html
    end
  end

  def raw_html( src )
    ( "<notextile>\n" << src.to_s ).chomp( "\n" ) << "\n</notextile>"
  end

  def outline
    @outline ||= begin
      count = 0
      headers = []
      body.gsub!( %r(<h1([^\n<>]*)>(.+?)
)m ) do
        attrs, title = $1, $2
        if attrs =~ /id="(.+?)"/
          id = $1
        else
          id = "section-#{ count += 1 }"
          attrs << %( id="#{ id }")
        end
        headers << [ id, title.strip ]
        %(
#{ title }
)
      end
      headers
    end
  end

  def preprocess
    [ @stylesheets, @scripts, @inline_styles ].each { | list | list.clear }

    source = self.source.gsub( WIKI_LINK_RX ) do
      raw, article_name, link_text = $~[ 0..2 ]
      if article = $article_index[ article_name ]
        link_text ||= article.title
        link_article( article, link_text )
      else raw
      end
    end

    relative_file = File.relative( @source_file )
    line_no = 0
    out = []
    block = tag = options = nil
    for line in source.split( $/ )
      line_no += 1
      if ( line =~ /^« *(\S+) *(.*)/ ) ... ( line =~ /^»/ )
        if tag.nil? then
          tag, options = $1, $project.yaml.load( "{ #$2 }" )
          tag = tag.downcase.to_sym

          options = options.with_defaults( :line => line_no + 1, :file => relative_file )
          block = ''
        elsif line =~ /^»/
          out << special_block( tag, block.chomp, options )
          tag = block = nil
        else
          block << line << $/
        end
      else
        out << line
      end
    end

    for list in [ @stylesheets, @scripts, @inline_styles ]
      list.compact!
      list.uniq!
    end

    out.compact!

    return( out.join( $/ ) )
  end

  def special_block( tag, content, options )
    case tag
    when :raw then raw_html( content )
    when :antlr then
      @stylesheets << 'ANTLR3.css'
      CodeFrame.new( tag, content, options )
    when :ruby then
      @stylesheets << "ruby.css"
      CodeFrame.new( tag, content, options )
    when :css then
      @stylesheets << "generic.css"
      options = options.with_defaults(
        :class => 'generic', :number_lines => false, :prompt => '~>'
      )
      CodeFrame.new( tag, content, options )
    when :style
      @inline_styles << content
      nil
    when :eval
      output = ERB.new( content, nil, '%' ).result( binding )
      raw_html( Markup.convert( output ) )
    when :cmd, :shell
      @stylesheets << 'generic.css'
      options = options.with_defaults(
        :class => 'generic', :number_lines => false, :prompt => '~>'
      )
      CodeFrame.new( tag, content, options )
    when :table
      Table.new( $project.yaml.load( content ).update( options ) )
    end
  end

  def convert_markup( textile )
    Markup.inline( textile )
  end

  def link_article( article, link_text = article.title )
    href = File.relative( article.output_file, @output_directory )
    %(#{ link_text })
  end

  def relative( file )
    File.relative( file, @output_directory )
  end

  private :raw_html
end
end


text:
package ui;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.swing.CellRendererPane;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.PanelUI;

import org.apache.log4j.Logger;

import model.graph.Edge;
import model.graph.GraphModel;
import model.graph.GraphSelectionModel;

import swingPlus.graph.GraphCellRenderer;
import swingPlus.graph.GraphEdgeRenderer;
import swingPlus.graph.JGraph;
import swingPlus.graph.ObjectPlacement;
import swingPlus.shared.CellRendererPane2;
import swingPlus.shared.JLogSlider;
import swingPlus.shared.KineticCoast;
import swingPlus.shared.border.DashedBorder;
import util.GraphicsUtil;
import util.IconCache;

import util.Messages;
import util.anim.AnimActionBase;
import util.anim.AnimTimer;
import util.anim.RangeTransformer;
import util.anim.SineTransform;
import util.colour.ColorUtilities;
import util.colour.ColourScheme;

public class GraphUI extends PanelUI {

	private static final Class<GraphUI> CLASSTYPE = GraphUI.class;
	private static final Logger LOGGER = Logger.getLogger (CLASSTYPE);
    private static final Cursor AREASELECTCURSOR = Toolkit.getDefaultToolkit().createCustomCursor
		(((ImageIcon)IconCache.makeIcon ("AreaSelectCursor")).getImage(), new Point (3, 2), "AreaSelect");
    private final static double RADDEG = 360.0 / (2.0 * Math.PI);
    public final static double SCALE_MIN = 0.03, SCALE_MAX = 10.0;

    public final static int NO_EDGES_SMALLER_THAN = 144; // 12 squared

    private final MouseAdapter mouseAdapt = new TreePanelMouseListener ();
    private final ComponentAdapter compAdapt = new MyComponentAdapter ();
    //private final BasicStroke rectOutline = new BasicStroke (2.0f);

    private JGraph graph;
    //private Line2D line = new Line2D.Double ();
    private boolean antiAliasFlag = false;
    private BufferedImage lastScreenImage, fadeInImage, fadeOutImage;
    private final JLabel dragLabel = new JLabel ();

    private final Point translatePoint = new Point (0, 0);
    private double oldScale = 1.0, scale = 1.0;
    private final Point offsetPoint = new Point (0, 0);
    private final ScaledMovement sMove = new ScaledMovement ();

    private OffScreenIndicator offScreenIndicatorInstance;

    private List<Rectangle> labelAreas;
    private List<Object> objectDrawOrder;

    protected CellRendererPane rendererPane;

    private static Color transBrushLink = new Color (255, 255, 0, 128);

    private JLogSlider scaleSlider;
	ChangeListener sliderListener = new ChangeListener () {
		@Override
		public void stateChanged (final ChangeEvent event) {
			final JLogSlider jsl = (JLogSlider)event.getSource();
			final double scale = jsl.getScaleFromValue ();
			setScale (scale, new Point (graph.getWidth() / 2, graph.getHeight()  / 2));
			LOGGER.debug (jsl.getScaleFromValue());
		}
	};
	private final Double ZERO = Double.valueOf (0.0);

    protected Insets edgeInsets = new Insets (0, 0, 0, 0);

	public static GraphUI createUI (final JComponent comp) {
		return new GraphUI();
	}

	@Override
	public void installUI (final JComponent comp) {
        super.installUI (comp);
        graph = (JGraph)comp;
        installDefaults (graph);
        installListeners ();
    }

    @Override
	public void uninstallUI (final JComponent comp) {
    	graph = (JGraph)comp;
        uninstallDefaults (graph);
        uninstallListeners ();
        super.uninstallUI (comp);
        graph = null;
    }

    protected void installDefaults (final JComponent tPanel) {
        //LookAndFeel.installColorsAndFont(BARLEY_PATTERN,
		//			 "Panel.background",
		//			 "Panel.foreground",
		//			 "Panel.font");
        //LookAndFeel.installBorder(BARLEY_PATTERN,"Panel.border");
        //LookAndFeel.installProperty(BARLEY_PATTERN, "opaque", Boolean.TRUE);
    	//setColours ();

    	graph.add (dragLabel);
    	setDragLabel ();
		dragLabel.setFont (Font.decode (Messages.getString (GraphicsUtil.GRAPHICPROPS, CLASSTYPE, "selectBoxFont")));
		dragLabel.setHorizontalAlignment (SwingConstants.CENTER);

        rendererPane = new CellRendererPane2();
        graph.add (rendererPane);
		//dragLabel.
        setSlider (new JLogSlider (JSlider.VERTICAL, -5, 3));

        offScreenIndicatorInstance = new OffScreenIndicator ();

        labelAreas = new ArrayList<Rectangle> ();
        objectDrawOrder = new ArrayList<Object> ();
    }

    protected void uninstallDefaults (final JComponent tPanel) {
        //LookAndFeel.uninstallBorder(tPanel);
    	graph.remove (dragLabel);
        graph.remove (rendererPane);
        rendererPane = null;
        removeSlider ();
    }

	protected void installListeners () {
		// Uninstall Handlers
		graph.addMouseListener (mouseAdapt);
		graph.addMouseMotionListener (mouseAdapt);
		graph.addMouseWheelListener (mouseAdapt);
		graph.addComponentListener (compAdapt);
	}

	protected void uninstallListeners () {
		// Uninstall Handlers
		graph.removeMouseListener (mouseAdapt);
		graph.removeMouseMotionListener (mouseAdapt);
		graph.removeMouseWheelListener (mouseAdapt);
		graph.removeComponentListener (compAdapt);
	}

	protected void uninstallKeyboardActions() {
		// empty method
	}

	/**
	 * Uninstalls the renderer pane.
	 */
	protected void uninstallComponents() {
		// empty method
	}

	public void setSlider (final JLogSlider newSlider) {
		if (scaleSlider != null) {
			newSlider.setMinimum (scaleSlider.getMinimum ());
			newSlider.setMaximum (scaleSlider.getMaximum ());
			newSlider.setValue (scaleSlider.getValue ());
			removeSlider ();
		}

		scaleSlider = newSlider;

		if (scaleSlider != null) {
			scaleSlider.addChangeListener (sliderListener);
			if (scaleSlider.getParent() != null) {
				scaleSlider.getParent().remove (scaleSlider);
			}
			graph.add (scaleSlider);
			graph.addPropertyChangeListener (scaleSlider);
			scaleSlider.setLocation (20, 20);
			scaleSlider.setSize (30, 128);
		}
	}

	void removeSlider () {
		scaleSlider.removeChangeListener (sliderListener);
		graph.removePropertyChangeListener (scaleSlider);
		graph.remove (scaleSlider);
	}

	//
	// Painting routines.
	//

	@Override
	// Overridden for performance reasons. No reason to blank background before paint
	// if we are blitting an image over the top anyways
    public void update (final Graphics graphics, final JComponent comp) {
    	paint (graphics, comp);
    }

	/**
	 * Main painting routine.
	 */
	@Override
	public void paint (final Graphics graphics, final JComponent comp) {
		initBuffer ();
		LOGGER.debug ("drawing");
		final Graphics gDraw = GraphicsUtil.primeImageGraphics (graphics, graphics.getClipBounds(), lastScreenImage, graph.getBackground(), UIConstants.ALL);
		antiAliasFlag = GraphicsUtil.isNonScreenImage ((Graphics2D)graphics);
		drawToImage (gDraw);

		if (!GraphicsUtil.isSVGGraphics (graphics)) {
			graphics.drawImage (lastScreenImage, translatePoint.x, translatePoint.y, comp);
		}
	}

    /**
	* Method that sets up off screen image for this class.

	* Must be called after parent component inputStream made visible, so correct screen dimensions are obtained,
	* but before an attempt inputStream made to repaint this component, because the off-screen image will not be available.
	*/
	protected void initBuffer () {
		final Rectangle rect = new Rectangle (0, 0, 0, 0);
		if (graph != null) {
			graph.computeVisibleRect (rect);
		}
		final Dimension dims = rect.getSize();
		translatePoint.setLocation (rect.getLocation());
		lastScreenImage = GraphicsUtil.initImage (lastScreenImage, graph, dims, Transparency.OPAQUE);
		fadeInImage = GraphicsUtil.initImage (fadeInImage, graph, dims, Transparency.TRANSLUCENT);
		fadeOutImage = GraphicsUtil.initImage (fadeOutImage, graph, dims, Transparency.TRANSLUCENT);

		//logger.info ("lastScreenImage "+lastScreenImage.getCapabilities (gc))
	}

	void clearBuffer () {
        GraphicsUtil.clearImage (lastScreenImage);
        GraphicsUtil.clearImage (fadeInImage);
        GraphicsUtil.clearImage (fadeOutImage);
        lastScreenImage = null;
        fadeInImage = null;
        fadeOutImage = null;
	}

	Image getLastScreenImage () { return lastScreenImage; }

	/**
	* Method that draws to an off-screen image the visualisation of the current state of the {@link Forest Forest} object.

	*/
	protected void drawToImage (final Graphics gDraw) {

        //synchronized (graph) {

		final long nano = System.nanoTime ();

	        final Graphics2D g2D = (Graphics2D)gDraw;
	        setAntiAlias (g2D, antiAliasFlag);

			// AlphaComposite.SrcAtop causes Batik SVG error
			// See https://issues.apache.org/bugzilla/show_bug.cgi?id=26466
	        // g2D.setComposite (AlphaComposite.SrcAtop);

	        g2D.translate (translatePoint.x, translatePoint.y);

	        offScreenIndicatorInstance.reset ();
	        objectDrawOrder.clear ();
	        labelAreas.clear ();

	        drawEdges (g2D, false);
	        final long nano3 = System.nanoTime();
	        drawNodes (g2D, false);
	        final long nano4 = System.nanoTime();
	        drawEdges (g2D, true);
	        final long nano5 = System.nanoTime();
	        drawNodes (g2D, true);
	        //long nano6 = System.nanoTime();
	        //graph.getRepulsiveForceCalculator().reveal (g2D, this, new Point2D.Double (0, 0));

	        offScreenIndicatorInstance.draw (g2D);
	        /*
	        if (!antiAliasFlag) {

	    		final Image images[] = {fadeOutImage, fadeInImage};
	    		final AlphaComposite composites[] = {TransparentLabelUI.getFadeOut(), TransparentLabelUI.getFadeIn()};

	    		for (int n = 0; n < images.length; n++) {
	    			final Image element = images [n];
	    			if (element != null && composites[n].getAlpha() > 0.0f) {
	    				g2D.setComposite (composites [n]);
	    				g2D.drawImage (element, 0, 0, panel);
	    			}
	    		}
	    		//g2D.setComposite (AlphaComposite.SrcAtop);
	        }
	        g2D.setComposite (AlphaComposite.SrcAtop);
	        */

	        setAntiAlias (g2D, false);

	       // long nano2 = System.nanoTime();
	        if (LOGGER.isDebugEnabled()) {
		        LOGGER.debug (((nano3-nano)+(nano5-nano4))/1e6+" milliseconds for repaint edges");
		        LOGGER.debug ((nano4-nano3)/1e6+" milliseconds for repaint nodes");
	        }
        //}
	}

	protected void drawEdges (final Graphics2D g2D, final boolean isSelected) {

		final GraphModel graphModel = graph.getFilteredModel();
		final Set<Object> nodes = graphModel.getNodes ();
		final Iterator<Object> nodeIterator = nodes.iterator();
        int edgeCount = 0;
        Rectangle rect = g2D.getClipBounds ();
        if (rect == null) {
        	rect = graph.getVisibleRect ();
        }
        scaleandPanRect2NodeRect (rect);
        final GraphSelectionModel gsm = graph.getSelectionModel();
        final boolean showAllNodeEdges = graph.isShowEdges();
        g2D.setColor (Color.black);

        if (graph.getModel().getEdgeCount() < 500) {
            g2D.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        }

        while (nodeIterator.hasNext()) {
        	final Object node = nodeIterator.next ();
        	final boolean showThisNodeEdges = gsm.isSelected (node);

        	if ((!isSelected && showAllNodeEdges) || (isSelected && showThisNodeEdges)) {
        		final Set<Edge> edges = graphModel.getEdges (node);
        		final Iterator<Edge> edgeIterator = edges.iterator ();

	        	while (edgeIterator.hasNext()) {
	        		final Edge edge = edgeIterator.next ();
	        		final boolean isSourceNode = !(edge.getNode2() == node) && (edge.getNode1() == node || edge.getNode1().equals (node));
	        		final boolean showOtherNodeEdges = gsm.isSelected (isSourceNode ? edge.getNode2() : edge.getNode1());
	        		final boolean bothNodesSelected = showThisNodeEdges & showOtherNodeEdges;
	        		//if (isSourceNode ||
	        		//	(isSelected && !isSourceNode && !showAllNodeEdges && showThisNodeEdges && !gsm.isSelected (edge.getNode1()))
	        		//	) { // don't draw edges twice
	        		if ((bothNodesSelected && isSelected) ^ (!isSelected && !bothNodesSelected && showAllNodeEdges)) {
		        		//gsm.setSelected (edge, bothNodesSelected);
	        			drawEdge (g2D, edge, rect);
		        		edgeCount++;
	        		}
	        	}
        	}
        }

        rendererPane.removeAll ();

        g2D.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_DEFAULT);

        if (LOGGER.isDebugEnabled()) {
        	LOGGER.debug ("Edgecount: "+edgeCount+" : "+isSelected);
        }
	}

	protected void drawEdge (final Graphics2D g2D, final Edge edge, final Rectangle visibleGraphArea) {
		final Object node1 = edge.getNode1();
		final Object node2 = edge.getNode2();

		final ObjectPlacement op1 = graph.getVisualRep (node1);
		final ObjectPlacement op2 = graph.getVisualRep (node2);

		final Point2D.Double loc1 = op1.getLocation ();
		final Point2D.Double loc2 = op2.getLocation ();

		if (visibleGraphArea.intersectsLine (loc1.x, loc1.y, loc2.x, loc2.y)) {
			final int x1 = nodeXtoScaleandPanX (loc1.getX());
			final int y1 = nodeYtoScaleandPanY (loc1.getY());
			final int x2 = nodeXtoScaleandPanX (loc2.getX());
			final int y2 = nodeYtoScaleandPanY (loc2.getY());
			final int d2 = ((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1));
			if (d2 >= NO_EDGES_SMALLER_THAN) {	// don't draw really small edges, occluded by the node reps usually anyways
				final GraphEdgeRenderer renderer = graph.getDefaultEdgeRenderer (edge.getEdgeObject().getClass());
				final Component component = graph.prepareEdgeRenderer (renderer, edge, x1, y1, x2, y2);
				edgeInsets = ((JComponent)component).getInsets (edgeInsets);

		        rendererPane.paintComponent (g2D, component, graph,
		        	Math.min (x1, x2) - edgeInsets.left,
		        	Math.min (y1, y2) - edgeInsets.top,
		        	Math.abs (x1 - x2) + 1 + edgeInsets.left + edgeInsets.right,
		        	Math.abs (y1 - y2) + 1 + edgeInsets.top + edgeInsets.bottom);
			}
		}
	}

	protected void drawNodes (final Graphics2D g2D, final boolean isSelected) {
		final GraphModel graphModel = graph.getFilteredModel();
		final Set<Object> nodes = graphModel.getNodes ();
        LOGGER.debug ("Filtered nodes: "+nodes.size());
        final Iterator<Object> nodeIterator = nodes.iterator();
        Rectangle rect = g2D.getClipBounds ();
        if (rect == null) {
        	rect = graph.getVisibleRect ();
        }
        scaleandPanRect2NodeRect (rect);
        final GraphSelectionModel gsm = graph.getSelectionModel();

        g2D.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        while (nodeIterator.hasNext()) {
        	final Object node = nodeIterator.next ();
        	if (gsm.isSelected (node) == isSelected) {
        		drawNode (g2D, node, rect);
        	}
        }

        g2D.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);

        rendererPane.removeAll ();
	}

	protected void drawNode (final Graphics2D g2D, final Object node, final Rectangle visibleGraphArea) {
		final ObjectPlacement objPlacement = graph.getVisualRep (node);
		if (objPlacement != null) {
			final Point2D.Double location = objPlacement.getLocation ();

			if (visibleGraphArea.contains (location) && node != null) {
				//System.err.println ("node: "+node);
				final GraphCellRenderer renderer = graph.getDefaultNodeRenderer (node.getClass());
				final Component component = graph.prepareNodeRenderer (renderer, node);
				final Dimension prefSize = component.getPreferredSize();
				final int width = prefSize.width;
				final int height = prefSize.height;

				final double minZoomX = component.getMinimumSize().getWidth() / width;
				final double minZoomY = component.getMinimumSize().getHeight() / height;
				final double scaleMin = Math.max (scale, Math.min (minZoomX, minZoomY));
				//System.out.println ("sm: "+scaleMin);
		        //g2D.scale (scale, scale);
				final int scaledWidth = (int)(width * scaleMin);
				final int scaledHeight = (int)(height * scaleMin);
				final Rectangle rect = new Rectangle (nodeXtoScaleandPanX ((int)location.getX()) - (scaledWidth >> 1),
		        		nodeYtoScaleandPanY ((int)location.getY()) - (scaledHeight >> 1),
		        		scaledWidth, scaledHeight);

				// Validate renderers that have sub-components so they get the correct sizes
				if (component instanceof Container && ((Container)component).getComponentCount() > 0) {
					rendererPane.paintComponent (g2D, component, graph, rect.x, rect.y, rect.width, rect.height, true);
				} else {
					rendererPane.paintComponent (g2D, component, graph, rect);
				}

		        labelAreas.add (rect);
		        objectDrawOrder.add (node);
		        //g2D.scale(1.0/scale, 1.0/scale);
			}
			else {
				final int outcode = visibleGraphArea.outcode (location);
				offScreenIndicatorInstance.incOutcodeCounter (outcode);
			}
		}
	}

	/*
	final void setBeforeAfterShots (final Set<DisplayRepGraph> add, final Set<DisplayRepGraph> remove) {

		final Dimension d = panel.getVisibleRect().getSize();
		fadeInImage = GraphicsUtil.initImage (fadeInImage, panel, d, Transparency.TRANSLUCENT);
		fadeOutImage = GraphicsUtil.initImage (fadeOutImage, panel, d, Transparency.TRANSLUCENT);

		final Graphics2D gOut = setEmptyBackground (fadeOutImage, new Color (0, 0, 0, 0));
        final Graphics2D gIn = setEmptyBackground (fadeInImage, new Color (0, 0, 0, 0));
        gIn.translate (-translatePoint.x, -translatePoint.y);
        gOut.translate (-translatePoint.x, -translatePoint.y);
        final Container BARLEY_PATTERN = new Container ();
        BARLEY_PATTERN.setSize (fadeInImage.getWidth (panel), fadeInImage.getHeight (panel));
        BARLEY_PATTERN.setBounds (0, 0, fadeInImage.getWidth (panel), fadeInImage.getHeight (panel));

        for (final DisplayRepGraph drg : add) {
        	//LOGGER.debug ("add drg: "+drg.getBounds());
        	final DisplayRepPlus drp = (DisplayRepPlus) drg;
        	SwingUtilities.paintComponent (gIn, drp, BARLEY_PATTERN, drp.getBounds());
        	//drg.setBounds (drg.getBounds (0.0));
        	//LOGGER.debug ("add drg a: "+drg.getBounds());
        }

        for (final DisplayRepGraph drg : remove) {
        	final DisplayRepPlus drp = (DisplayRepPlus) drg;
        	final Rectangle r = drp.getBounds();
        	SwingUtilities.paintComponent (gOut, drp, BARLEY_PATTERN, drp.getBounds());
        	drp.setBounds (r);
        }

        gIn.translate (translatePoint.x, translatePoint.y);
        gOut.translate (translatePoint.x, translatePoint.y);

        //LOGGER.debug ("images+ :"+fadeInImage.getWidth()+", "+fadeOutImage.getWidth());
	}
	*/

	final void setAntiAlias (final Graphics2D g2d, final boolean bool) {
		g2d.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
				bool ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
	}

	final void setAntiAliasFlag (final boolean bool) {
		antiAliasFlag = bool;
	}

	final void setColours (final ColourScheme colourScheme) {
	    transBrushLink = new Color (255, 255, 0, 128);
	    setDragLabel ();
	}

	final void setDragLabel () {
	    dragLabel.setBackground (transBrushLink);
		dragLabel.setForeground (Color.white);
		dragLabel.setBorder (new DashedBorder (transBrushLink,
			new BasicStroke (2.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.5f, new float[] {8.0f, 8.0f}, 0.0f)) );
	}

	public void nodePoint2ScaleandPanPoint (final Point point) {
        point.x = nodeXtoScaleandPanX (point.x);
        point.y = nodeYtoScaleandPanY (point.y);
	}

	public void scaleandPanPoint2NodePoint (final Point point) {
        point.x = scaleandPanXtoNodeX (point.x);
        point.y = scaleandPanYtoNodeY (point.y);
	}

	protected void nodeRect2ScaleandPanRect (final Rectangle rect) {
        rect.x = nodeXtoScaleandPanX (rect.x);
        rect.y = nodeYtoScaleandPanY (rect.y);
        rect.width = (int)(rect.width * scale);
        rect.height = (int)(rect.height * scale);
	}

	protected void scaleandPanRect2NodeRect (final Rectangle rect) {
        rect.x = scaleandPanXtoNodeX (rect.x);
        rect.y = scaleandPanYtoNodeY (rect.y);
        rect.width = (int)(rect.width / scale);
        rect.height = (int)(rect.height / scale);
	}

	private int nodeXtoScaleandPanX (final double x) {
		return (int)((x - offsetPoint.x) * scale);
	}

	private int nodeYtoScaleandPanY (final double y) {
		return (int)((y - offsetPoint.y) * scale);
	}

	private int scaleandPanXtoNodeX (final int x) {
		return (int) (x / scale) + offsetPoint.x;
	}

	private int scaleandPanYtoNodeY (final int y) {
		return (int) (y / scale) + offsetPoint.y;
	}

	public int logic2ViewCoordX (final double x) {
		return nodeXtoScaleandPanX (x);
	}

	public int logic2ViewCoordY (final double y) {
		return nodeYtoScaleandPanY (y);
	}

	protected void rotate (final Point2D.Double loc, final int angleDegrees, final int aboutx, final int abouty) {
		final double angleRad = angleDegrees / RADDEG;
		final double cos = Math.cos (angleRad);
		final double sin = Math.sin (angleRad);
		final double xx = ((loc.x - aboutx) * cos) - ((loc.y - abouty) * sin);
		final double yy = ((loc.x - aboutx) * sin) + ((loc.y - abouty) * cos);
		loc.setLocation (xx + aboutx, yy + abouty);
	}

	protected void rotateAll (final int angleDegrees) {

		final int x = graph.getWidth() / 2;
		final int y = graph.getHeight () / 2;
		final int aboutx = scaleandPanXtoNodeX (x);
		final int abouty = scaleandPanYtoNodeY (y);

		final Collection<ObjectPlacement> nodeLocations = graph.getObjectPlacementMapping().getAllPlacements();
		final Iterator<ObjectPlacement> nodeIterator = nodeLocations.iterator();

        while (nodeIterator.hasNext()) {
        	final ObjectPlacement op = nodeIterator.next();
        	rotate (op.getLocation(), angleDegrees, aboutx, abouty);
        }
	}

	public Object getNodeAt (final Point point) {
		Object obj = null;
		for (int n = objectDrawOrder.size(); --n >= 0 && obj == null;) {
			if (labelAreas.get(n).contains(point)) {
				obj = objectDrawOrder.get (n);
			}
		}
		//Object obj = graph.getNearestTo (scaleandPanPoint2NodePoint (BARLEY_PATTERN));
		return obj;
	}

	public void setScale (final double newScale, final Point zoomPoint) {
		scale = Math.max (SCALE_MIN, Math.min (SCALE_MAX, newScale));
		LOGGER.debug ("scale: "+scale+"\t oldScale: "+oldScale);
		final double deltaScale = (scale / oldScale) - 1.0;
		offsetPoint.setLocation (
			offsetPoint.getX() + ((zoomPoint.getX() * deltaScale) / scale),
			offsetPoint.getY() + ((zoomPoint.getY() * deltaScale) / scale)
		);
		//System.err.println ("sclae: "+scale);
		oldScale = scale;
		graph.firePropertyChange ("scale", ZERO, Double.valueOf (scale));
		graph.repaint ();
	}

	public double getScale () { return scale; }

	public void moveTo (final Object obj, final Point objToHere) {
		sMove.moveTo (obj, objToHere);
	}

	public void fitTo (final Collection<Object> objs) {
		sMove.moveTo (objs);
	}

	protected void setMouseOverObject (final Object newObj) {
		((TreePanelMouseListener)mouseAdapt).setMouseOverObject(newObj);
	}

	class TreePanelMouseListener extends MouseAdapter {

		private Point lastPoint = null, secondLastPoint = new Point(), startPoint = null, endPoint = null;
		private long mouseEventTime, lastMouseEventTime;
		private Object selectedObject = null;
		private Object mouseOverObject = null;
		private boolean wasDragging = false;
		KineticCoast kTimer = new KineticCoast (20, 0.05, true);
     	// public void mousePressed (MouseEvent e)
		// Big routine for detecting mouse presses.
		// Options are	1) Right mouse button clicked on no information - enter drag mode
		//							2) Left mouse button clciked on no information - ignore
		//							3) Right mouse button clicked on node - clear all other selections and highlight
		//							4) Left mouse button clicked on node - highlight node in addition to previous selections
		//							5) Mouse button clicked on hierarchy name - toggle hidden/displayed

		@Override
		public void mousePressed (final MouseEvent e) {
			kTimer.stop ();

			startPoint = e.getPoint ();
			lastPoint = e.getPoint ();
			//if (dragLabel.getParent() != graph) {
			//	graph.add (dragLabel);
			//	graph.setComponentZOrder (dragLabel, 0);
			//}
			//dragLabel.setVisible (true);

			final Point point = e.getPoint ();
			scaleandPanPoint2NodePoint (point); // adjust screen coords to node coords

			final Object obj = getNodeAt (e.getPoint ());
			selectedObject = obj;
			if (obj != null) {
				final ObjectPlacement op = graph.getObjectPlacementMapping().getPlacement (obj);
				//GraphUI.this.scaleandPanPoint2NodePoint(BARLEY_PATTERN);
				if (op != null) {
					op.setForceInactive (true);
					point.setLocation (op.getLocation());
					nodePoint2ScaleandPanPoint (point);
					final double dsq = e.getPoint().distanceSq (point);
					LOGGER.debug ("BARLEY_PATTERN: "+point+"\td: "+dsq+"\t ");
					selectedObject = (dsq < 400.0 ? obj : null);
				}
			}
			LOGGER.debug ("so: "+selectedObject);
		}

		// void mouseMoved (mouseEvent e)
		// What to do when mouse pointer moves over visualisation (but not dragged).
		@Override
		public void mouseMoved (final MouseEvent event) {

			final Object obj = getNodeAt (event.getPoint ());
			if (obj != mouseOverObject) {
				mouseOverObject = obj;
				//graph.setToolTipText (obj == null ? "" : obj.toString());

				if (obj != null) {
					final Graphics graphics = graph.getGraphics();
			        Rectangle r = graphics.getClipBounds ();
			        if (r == null) {
			        	r = graph.getVisibleRect ();
			        }
			        scaleandPanRect2NodeRect (r);
			        drawNode ((Graphics2D)graphics, obj, r);
				}
			}
 		}

		@Override
		public void mouseClicked (final MouseEvent event) {
			if (event.getButton() == MouseEvent.BUTTON1) {
				if (selectedObject != null) {
					final GraphSelectionModel gsm = graph.getSelectionModel();
					gsm.setValueIsAdjusting (true);
					final boolean newSelectState = !gsm.isSelected (selectedObject);
					gsm.setSelected (selectedObject, newSelectState);

					final Set<Edge> edges = graph.getModel().getEdges (selectedObject);
					final Iterator<Edge> edgeIterator = edges.iterator ();
					while (edgeIterator.hasNext()) {
						final Edge edge = edgeIterator.next ();
						final Object otherNode = edge.getNode1().equals (selectedObject) ? edge.getNode2() : edge.getNode1();
						gsm.setSelected (otherNode, newSelectState);
					}

					gsm.setValueIsAdjusting (false);
				}
			}
			else if (event.getButton() == MouseEvent.BUTTON3) {
				if (mouseOverObject != null) {
					final Set<Edge> edges = graph.getFilteredModel().getEdges (mouseOverObject);

					if (!edges.isEmpty ()) {
						graph.getRightClickMenu().setNodeDetails (graph, event.getPoint(), mouseOverObject);
					}
				}
			}
		}

		// void mouseExited (mouseEvent e)
		// Tidy up main visual panel when mouse pointer inputStream no longer in it.

		@Override
		public void mouseExited (final MouseEvent event) {
			final Component comp = event.getComponent();
			comp.setCursor (Cursor.getPredefinedCursor (Cursor.DEFAULT_CURSOR));
			selectedObject = null;
		}

		@Override
		public void mouseEntered (final MouseEvent event) {
			LOGGER.info ("Entering DAG Panel");
			final Component comp = event.getComponent();
			comp.setCursor (AREASELECTCURSOR);
			selectedObject = null;
		}

		@Override
		public void mouseDragged (final MouseEvent event) {

			wasDragging = true;
			final Component comp = event.getComponent();
			comp.setCursor (Cursor.getPredefinedCursor (Cursor.MOVE_CURSOR));

			final int modifiers = event.getModifiersEx();

			if (selectedObject == null) {
				final double dragxoffset = (lastPoint.getX() - event.getX());
				final double dragyoffset = (lastPoint.getY() - event.getY());
				secondLastPoint.setLocation (lastPoint);

				lastMouseEventTime = (mouseEventTime == 0 ? event.getWhen() - 20 : mouseEventTime);
				mouseEventTime = event.getWhen();

				lastPoint.setLocation (event.getX(), event.getY());
				if ((modifiers & MouseEvent.BUTTON1_DOWN_MASK) > 0) {	// Action for left mouse drag on background
					offsetPoint.setLocation (offsetPoint.getX() + (dragxoffset / scale),
							offsetPoint.getY() + (dragyoffset / scale));
					graph.repaint();
				}
			}
			else if ((modifiers & MouseEvent.BUTTON1_DOWN_MASK) > 0) { // Action for left mouse drag on node
				final ObjectPlacement op = graph.getObjectPlacementMapping().getPlacement (selectedObject);
				if (op != null) {
					op.getLocation().setLocation (scaleandPanXtoNodeX (event.getX()), scaleandPanYtoNodeY (event.getY()));
				}
				graph.repaint ();
			}
		}

		@Override
		public void mouseReleased (final MouseEvent event) {
			final Component comp = event.getComponent();
			comp.setCursor (AREASELECTCURSOR);

			dragLabel.setVisible (false);
			endPoint = event.getPoint();

			if (selectedObject != null && !startPoint.equals(endPoint)) {
				final ObjectPlacement op = graph.getObjectPlacementMapping().getPlacement (selectedObject);
				op.getLocation().setLocation (scaleandPanXtoNodeX (event.getX()), scaleandPanYtoNodeY (event.getY()));
				op.setForceInactive (false);
				graph.restartWorker ();
			} else if (wasDragging) {
				wasDragging = false;
				final double dragxoffset = (secondLastPoint.getX() - event.getX());
				final double dragyoffset = (secondLastPoint.getY() - event.getY());

				kTimer.startCoast (dragxoffset, dragyoffset, event.getWhen() - lastMouseEventTime, offsetPoint, scale, graph);
			}
		}

		@Override
		public void mouseWheelMoved (final MouseWheelEvent event) {
			if (scale >= SCALE_MIN && scale <= SCALE_MAX) {
				scale /= Math.pow (2, event.getWheelRotation() / 15.0);
				//System.err.println ("scale b : "+scale+", wr: "+event.getWheelRotation());
				scaleSlider.removeChangeListener (sliderListener);
				setScale (scale, event.getPoint());
				scaleSlider.addChangeListener (sliderListener);
				//System.err.println ("scale a: "+scale+", wr: "+event.getWheelRotation());
			}
		}

		public void setMouseOverObject (final Object newObj) {
			mouseOverObject = newObj;
		}
	}

	class MyComponentAdapter extends ComponentAdapter {

		final private Dimension oldSize = new Dimension (0, 0);
		@Override
		public void componentResized (final ComponentEvent event) {
			final Dimension newSize = event.getComponent().getSize();
			if (!oldSize.equals (newSize)) {
				oldSize.setSize (newSize);
				graph.repaint ();
			}
		}
	}

	/**
	 *
	 * @author cs22
	 *
	 * Class that draws triangle arrows at compass points on screen
	 * along with a text version of counter stating how many nodes are
	 * off-screen in each particular direction
	 */
	class OffScreenIndicator {

		private final int[] outcodeCounters = new int [16];
		final private Shape outCodeTriangle = new Polygon (new int [] {0, 20, 0}, new int [] {0, 0, 20}, 3);
		final private Shape[] outCodeTriangles = new Shape [8];
		final private int[] outCode2TriangleIndex = new int[] {-1, 7, 1, 0, 3, -1, 2, -1, 5, 6, -1, -1, 4, -1, -1, -1};
		final private Color triangleFillColour = ColorUtilities.decodeWithAlpha (Messages.getString (GraphicsUtil.GRAPHICPROPS, GraphUI.class, "TriangleFillColour"));
		final private Color triangleDrawColour = ColorUtilities.decodeWithAlpha (Messages.getString (GraphicsUtil.GRAPHICPROPS, GraphUI.class, "TriangleDrawColour"));

		OffScreenIndicator () {
			final AffineTransform at = new AffineTransform ();
	        for (int n = 0; n < outCodeTriangles.length; n++) {
	        	outCodeTriangles [n] = at.createTransformedShape (outCodeTriangle);
	        	at.rotate (Math.PI / 4.0);
	        }
		}

		void reset () {
	        for (int n = 0; n < outcodeCounters.length; n++) {
	        	outcodeCounters [n] = 0;
	        }
		}

		void incOutcodeCounter (final int outcode) {
			outcodeCounters [outcode]++;
		}

		protected void draw (final Graphics2D g2D) {

			final AffineTransform originalTransform = g2D.getTransform();

			for (int n = 0; n < outcodeCounters.length; n++) {
				final int count = outcodeCounters [n];
				if (count > 0) {

					final int x = ((n & Rectangle2D.OUT_LEFT) > 0) ? 0 :
							((n & Rectangle2D.OUT_RIGHT) > 0) ? graph.getWidth() - 1: graph.getWidth() / 2;
					final int y = ((n & Rectangle2D.OUT_TOP) > 0) ? 0 :
							((n & Rectangle2D.OUT_BOTTOM) > 0) ? graph.getHeight() - 1: graph.getHeight() / 2;

					g2D.translate(x, y);
					final int index = outCode2TriangleIndex [n];
					if (index >= 0 && index < outCodeTriangles.length) {
						final Shape s = outCodeTriangles [outCode2TriangleIndex [n]];
						g2D.setColor (triangleFillColour);
						g2D.fill (s);
						g2D.setColor (triangleDrawColour);
						g2D.draw (s);
						//g2D.translate(-x, -y);

						final String countString = Integer.toString (count);
						final Rectangle2D stringBounds = g2D.getFontMetrics().getStringBounds (countString, g2D);
						g2D.setColor (Color.black);
						final int dx = ((n & Rectangle2D.OUT_LEFT) > 0) ? 0 :
							((n & Rectangle2D.OUT_RIGHT) > 0) ? (int)-stringBounds.getWidth() : (int)-stringBounds.getWidth() / 2;
						final int dy = (int)(stringBounds.getHeight() * 3.0 / 4.0) +
							(((n & Rectangle2D.OUT_TOP) > 0) ? 0 :
							((n & Rectangle2D.OUT_BOTTOM) > 0) ? (int)-stringBounds.getHeight() : (int)-stringBounds.getHeight() / 2
						);

						g2D.translate(-x, -y);
						g2D.drawString (countString, x + dx, y + dy);

					}
				}
			}

			g2D.setTransform (originalTransform);
		}
	}

	public class ScaledMovement {

		Point startCenter, endCenter, curCenter;
		double startZoom, endZoom;
		Rectangle visRect;
		Dimension viewMargin = new Dimension (180, 140);	// Boundary around rectangle when fitting to a collection of objects
		Timer anim;

		ScaledMovement () {
			startCenter = new Point ();
			endCenter = new Point ();
			curCenter = new Point ();
			startZoom = 1.0;
			endZoom = 1.0;

			anim = new AnimTimer (25, new MoveOffsetAnim (0.02, new SineTransform ()));
		}

		public void moveTo (final Object obj, Point underPoint) {
			if (obj != null) {
				final ObjectPlacement placement = graph.getObjectPlacementMapping().getPlacement (obj);

				if (placement != null) {
					final Point p = new Point ((int)placement.getLocation().getX(), (int)placement.getLocation().getY());

					visRect = graph.getVisibleRect ();

					if (underPoint == null) {
						underPoint = new Point ((int)visRect.getCenterX(), (int)visRect.getCenterY());
					}
					scaleandPanPoint2NodePoint (underPoint);
					scaleandPanRect2NodeRect (visRect);

					startCenter.setLocation (visRect.getCenterX(), visRect.getCenterY());
					endCenter.setLocation (visRect.getCenterX(), visRect.getCenterY());
					endCenter.translate (p.x - underPoint.x, p.y - underPoint.y);

					LOGGER.debug ("p: "+p);
					LOGGER.debug ("midPoint: "+underPoint);
					LOGGER.debug ("offsetPoint: "+offsetPoint);
					//offsetPoint.translate (p.x - underPoint.x, p.y - underPoint.y);
					LOGGER.debug ("offsetPoint: "+offsetPoint);

					startZoom = scale;
					endZoom = scale;

					// Make the target object the new mouseover object, so it is set up for the right click menu
					GraphUI.this.setMouseOverObject (obj);

					anim.restart ();
				}
			}
		}

		public void moveTo (final Collection<Object> objs) {

			if (objs != null) {
				Rectangle rect = null;
				final Iterator<Object> iObj = objs.iterator ();

				while (iObj.hasNext ()) {
					final Object node = iObj.next ();
					final ObjectPlacement placement = graph.getObjectPlacementMapping().getPlacement (node);

					if (placement != null) {
						if (rect == null) {
							rect = new Rectangle ((int)placement.getLocation().getX(),
									(int)placement.getLocation().getY(),
									1, 1);
						}
						else {
							rect.add (placement.getLocation ());
						}
					}
				}

				if (rect != null) {
					rect.grow (viewMargin.width, viewMargin.height);

					visRect = graph.getVisibleRect ();
					// Change screen bound coordinates to node space coordinates
					scaleandPanRect2NodeRect (visRect);

					final double yRatio = rect.getHeight() / visRect.getHeight();
					final double xRatio = rect.getWidth() / visRect.getWidth();

					startZoom = scale;
					endZoom = scale / Math.max (yRatio, xRatio);

					// Adjust end zoom to fit an exact point on JSlider, so no 'jerks' at end of animation
					endZoom = scaleSlider.roundedValue (endZoom);

					startCenter.setLocation ((int)visRect.getCenterX(), (int)visRect.getCenterY());
					endCenter.setLocation ((int)rect.getCenterX(), (int)rect.getCenterY());

					anim.restart ();
				}
			}
		}

		protected void setViewMargin (final Dimension newMargin) {
			viewMargin.setSize (newMargin);
		}

		protected Dimension getViewMargin () {
			return viewMargin;
		}

		class MoveOffsetAnim extends AnimActionBase {

	    	/**
			 *
			 */
			private static final long serialVersionUID = 5718087044458098875L;

	    	MoveOffsetAnim (final double stepVal, final RangeTransformer newrt) {
	    		super (stepVal, newrt);
	    	}

	        @Override
			public void doWork (final ActionEvent evt) {
	        	final double per = this.getPercentTransition (MOVE) / 100.0;

	        	// Interpolate between the two center of view coordinates
	        	final int x = (int)((endCenter.x - startCenter.x) * per);
	        	final int y = (int)((endCenter.y - startCenter.y) * per);
	        	curCenter.setLocation (startCenter.x + x, startCenter.y + y);

	        	// Interpolate the zoom value
	        	final double zoom = (endZoom - startZoom) * per;
	        	scale = startZoom + zoom;
	        	oldScale = scale;

	        	// Using the current interpolated zoom value and center point
	        	// work out what the current top-left point would be (as that
	        	// is what node space coordinates are based on)
	        	final double curHalfWidth = (visRect.width * startZoom / scale) / 2.0;
	        	final double curHalfHeight = (visRect.height * startZoom / scale) / 2.0;
	        	offsetPoint.setLocation (curCenter.x - (int)curHalfWidth,
	        			curCenter.y - (int)curHalfHeight);

	        	// Repaint
	            graph.repaint ();
	        }

	        @Override
	        public void animationFinished () {
	        	//EMPTY
	        }

	        @Override
			public void cleanUp () {
	        	super.cleanUp ();
	        	graph.firePropertyChange ("scale", ZERO, Double.valueOf (scale));
	        	graph.repaint ();
	        }
	    }
	}
}


text:
'use strict';

angular.module('mean.school').config(['$stateProvider',
  function($stateProvider) {
    $stateProvider
    .state('student-dashboard', {
      url: '/school/student',
      controller: 'StudentDashboardController as ctrl',
      templateUrl: 'school/views/student-dashboard/index.html'
    })
    ;
  }
]);